blob: 40447c7ea2940f05d8ece8ae165ff9382d0c6768 [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
Derek Foremanf8180982014-10-16 16:37:02 -050028#include <stdbool.h>
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -040029#include <stdlib.h>
Kristian Høgsberg25894fc2012-09-05 22:06:26 -040030#include <string.h>
31#include <ctype.h>
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +030032#include <float.h>
33#include <assert.h>
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +020034#include <linux/input.h>
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -040035
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010036#include "gl-renderer.h"
Sam Spilsbury619859c2013-09-13 10:01:21 +080037#include "vertex-clipping.h"
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010038
39#include <EGL/eglext.h>
40#include "weston-egl-ext.h"
Kristian Høgsbergd7c17262012-09-05 21:54:15 -040041
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010042struct gl_shader {
John Kåre Alsaker40684142012-11-13 19:10:25 +010043 GLuint program;
44 GLuint vertex_shader, fragment_shader;
45 GLint proj_uniform;
46 GLint tex_uniforms[3];
47 GLint alpha_uniform;
48 GLint color_uniform;
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +030049 const char *vertex_source, *fragment_source;
John Kåre Alsaker40684142012-11-13 19:10:25 +010050};
51
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +020052#define BUFFER_DAMAGE_COUNT 2
53
Jason Ekstrande5512d42014-02-04 21:36:38 -060054enum gl_border_status {
55 BORDER_STATUS_CLEAN = 0,
56 BORDER_TOP_DIRTY = 1 << GL_RENDERER_BORDER_TOP,
57 BORDER_LEFT_DIRTY = 1 << GL_RENDERER_BORDER_LEFT,
58 BORDER_RIGHT_DIRTY = 1 << GL_RENDERER_BORDER_RIGHT,
59 BORDER_BOTTOM_DIRTY = 1 << GL_RENDERER_BORDER_BOTTOM,
60 BORDER_ALL_DIRTY = 0xf,
61 BORDER_SIZE_CHANGED = 0x10
62};
63
Jason Ekstrand0b61bf42013-10-27 22:24:54 -050064struct gl_border_image {
65 GLuint tex;
66 int32_t width, height;
67 int32_t tex_width;
Jason Ekstrand0b61bf42013-10-27 22:24:54 -050068 void *data;
69};
70
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010071struct gl_output_state {
John Kåre Alsaker94659272012-11-13 19:10:18 +010072 EGLSurface egl_surface;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +020073 pixman_region32_t buffer_damage[BUFFER_DAMAGE_COUNT];
Derek Foreman4c582662014-10-09 18:39:44 -050074 int buffer_damage_index;
Jason Ekstrande5512d42014-02-04 21:36:38 -060075 enum gl_border_status border_damage[BUFFER_DAMAGE_COUNT];
Jason Ekstrand0b61bf42013-10-27 22:24:54 -050076 struct gl_border_image borders[4];
Jason Ekstrande5512d42014-02-04 21:36:38 -060077 enum gl_border_status border_status;
John Kåre Alsaker94659272012-11-13 19:10:18 +010078};
79
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +030080enum buffer_type {
81 BUFFER_TYPE_NULL,
82 BUFFER_TYPE_SHM,
83 BUFFER_TYPE_EGL
84};
85
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010086struct gl_surface_state {
John Kåre Alsaker878f4492012-11-13 19:10:23 +010087 GLfloat color[4];
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010088 struct gl_shader *shader;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +010089
90 GLuint textures[3];
91 int num_textures;
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +030092 int needs_full_upload;
Pekka Paalanen81ee3f52012-12-04 15:58:16 +020093 pixman_region32_t texture_damage;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +010094
Neil Roberts4d085e72014-04-07 15:01:01 +010095 /* These are only used by SHM surfaces to detect when we need
96 * to do a full upload to specify a new internal texture
97 * format */
98 GLenum gl_format;
99 GLenum gl_pixel_type;
100
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100101 EGLImageKHR images[3];
102 GLenum target;
103 int num_images;
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200104
105 struct weston_buffer_reference buffer_ref;
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +0300106 enum buffer_type buffer_type;
Pekka Paalanen68033ac2012-12-04 15:58:15 +0200107 int pitch; /* in pixels */
Alexander Larsson4ea95522013-05-22 14:41:37 +0200108 int height; /* in pixels */
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +0400109 int y_inverted;
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300110
111 struct weston_surface *surface;
112
113 struct wl_listener surface_destroy_listener;
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +0300114 struct wl_listener renderer_destroy_listener;
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100115};
116
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100117struct gl_renderer {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100118 struct weston_renderer base;
119 int fragment_shader_debug;
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400120 int fan_debug;
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +0300121 struct weston_binding *fragment_binding;
122 struct weston_binding *fan_binding;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100123
124 EGLDisplay egl_display;
125 EGLContext egl_context;
126 EGLConfig egl_config;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100127
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400128 struct wl_array vertices;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400129 struct wl_array vtxcnt;
130
John Kåre Alsaker320711d2012-11-13 19:10:27 +0100131 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
132 PFNEGLCREATEIMAGEKHRPROC create_image;
133 PFNEGLDESTROYIMAGEKHRPROC destroy_image;
134
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -0600135#ifdef EGL_EXT_swap_buffers_with_damage
136 PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage;
137#endif
138
John Kåre Alsaker320711d2012-11-13 19:10:27 +0100139 int has_unpack_subimage;
140
141 PFNEGLBINDWAYLANDDISPLAYWL bind_display;
142 PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
143 PFNEGLQUERYWAYLANDBUFFERWL query_buffer;
144 int has_bind_display;
145
146 int has_egl_image_external;
147
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200148 int has_egl_buffer_age;
149
Neil Roberts77c1a5b2014-03-07 18:05:50 +0000150 int has_configless_context;
151
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100152 struct gl_shader texture_shader_rgba;
153 struct gl_shader texture_shader_rgbx;
154 struct gl_shader texture_shader_egl_external;
155 struct gl_shader texture_shader_y_uv;
156 struct gl_shader texture_shader_y_u_v;
157 struct gl_shader texture_shader_y_xuxv;
158 struct gl_shader invert_color_shader;
159 struct gl_shader solid_shader;
160 struct gl_shader *current_shader;
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +0300161
162 struct wl_signal destroy_signal;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100163};
John Kåre Alsaker94659272012-11-13 19:10:18 +0100164
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100165static inline struct gl_output_state *
John Kåre Alsaker94659272012-11-13 19:10:18 +0100166get_output_state(struct weston_output *output)
167{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100168 return (struct gl_output_state *)output->renderer_state;
John Kåre Alsaker94659272012-11-13 19:10:18 +0100169}
170
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300171static int
172gl_renderer_create_surface(struct weston_surface *surface);
173
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100174static inline struct gl_surface_state *
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100175get_surface_state(struct weston_surface *surface)
176{
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300177 if (!surface->renderer_state)
178 gl_renderer_create_surface(surface);
179
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100180 return (struct gl_surface_state *)surface->renderer_state;
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100181}
182
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100183static inline struct gl_renderer *
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100184get_renderer(struct weston_compositor *ec)
185{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100186 return (struct gl_renderer *)ec->renderer;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100187}
188
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400189static const char *
190egl_error_string(EGLint code)
191{
192#define MYERRCODE(x) case x: return #x;
193 switch (code) {
194 MYERRCODE(EGL_SUCCESS)
195 MYERRCODE(EGL_NOT_INITIALIZED)
196 MYERRCODE(EGL_BAD_ACCESS)
197 MYERRCODE(EGL_BAD_ALLOC)
198 MYERRCODE(EGL_BAD_ATTRIBUTE)
199 MYERRCODE(EGL_BAD_CONTEXT)
200 MYERRCODE(EGL_BAD_CONFIG)
201 MYERRCODE(EGL_BAD_CURRENT_SURFACE)
202 MYERRCODE(EGL_BAD_DISPLAY)
203 MYERRCODE(EGL_BAD_SURFACE)
204 MYERRCODE(EGL_BAD_MATCH)
205 MYERRCODE(EGL_BAD_PARAMETER)
206 MYERRCODE(EGL_BAD_NATIVE_PIXMAP)
207 MYERRCODE(EGL_BAD_NATIVE_WINDOW)
208 MYERRCODE(EGL_CONTEXT_LOST)
209 default:
210 return "unknown";
211 }
212#undef MYERRCODE
213}
214
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +0300215static void
Pekka Paalanen326529f2012-11-27 12:25:25 +0200216gl_renderer_print_egl_error_state(void)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400217{
218 EGLint code;
219
220 code = eglGetError();
221 weston_log("EGL error state: %s (0x%04lx)\n",
222 egl_error_string(code), (long)code);
223}
224
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400225#define max(a, b) (((a) > (b)) ? (a) : (b))
226#define min(a, b) (((a) > (b)) ? (b) : (a))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400227
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300228/*
229 * Compute the boundary vertices of the intersection of the global coordinate
230 * aligned rectangle 'rect', and an arbitrary quadrilateral produced from
231 * 'surf_rect' when transformed from surface coordinates into global coordinates.
232 * The vertices are written to 'ex' and 'ey', and the return value is the
233 * number of vertices. Vertices are produced in clockwise winding order.
234 * Guarantees to produce either zero vertices, or 3-8 vertices with non-zero
235 * polygon area.
236 */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400237static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500238calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400239 pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
240{
Sam Spilsbury619859c2013-09-13 10:01:21 +0800241
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300242 struct clip_context ctx;
243 int i, n;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400244 GLfloat min_x, max_x, min_y, max_y;
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300245 struct polygon8 surf = {
246 { surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1 },
247 { surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2 },
248 4
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400249 };
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400250
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300251 ctx.clip.x1 = rect->x1;
252 ctx.clip.y1 = rect->y1;
253 ctx.clip.x2 = rect->x2;
254 ctx.clip.y2 = rect->y2;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400255
256 /* transform surface to screen space: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300257 for (i = 0; i < surf.n; i++)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500258 weston_view_to_global_float(ev, surf.x[i], surf.y[i],
259 &surf.x[i], &surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400260
261 /* find bounding box: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300262 min_x = max_x = surf.x[0];
263 min_y = max_y = surf.y[0];
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400264
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300265 for (i = 1; i < surf.n; i++) {
266 min_x = min(min_x, surf.x[i]);
267 max_x = max(max_x, surf.x[i]);
268 min_y = min(min_y, surf.y[i]);
269 max_y = max(max_y, surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400270 }
271
272 /* First, simple bounding box check to discard early transformed
273 * surface rects that do not intersect with the clip region:
274 */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300275 if ((min_x >= ctx.clip.x2) || (max_x <= ctx.clip.x1) ||
276 (min_y >= ctx.clip.y2) || (max_y <= ctx.clip.y1))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400277 return 0;
278
279 /* Simple case, bounding box edges are parallel to surface edges,
280 * there will be only four edges. We just need to clip the surface
281 * vertices to the clip rect bounds:
282 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500283 if (!ev->transform.enabled)
Sam Spilsbury619859c2013-09-13 10:01:21 +0800284 return clip_simple(&ctx, &surf, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400285
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300286 /* Transformed case: use a general polygon clipping algorithm to
287 * clip the surface rectangle with each side of 'rect'.
288 * The algorithm is Sutherland-Hodgman, as explained in
289 * http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm
290 * but without looking at any of that code.
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400291 */
Sam Spilsbury619859c2013-09-13 10:01:21 +0800292 n = clip_transformed(&ctx, &surf, ex, ey);
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300293
294 if (n < 3)
295 return 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400296
297 return n;
298}
299
Derek Foremanf8180982014-10-16 16:37:02 -0500300static bool
301merge_down(pixman_box32_t *a, pixman_box32_t *b, pixman_box32_t *merge)
302{
303 if (a->x1 == b->x1 && a->x2 == b->x2 && a->y1 == b->y2) {
304 merge->x1 = a->x1;
305 merge->x2 = a->x2;
306 merge->y1 = b->y1;
307 merge->y2 = a->y2;
308 return true;
309 }
310 return false;
311}
312
313static int
314compress_bands(pixman_box32_t *inrects, int nrects,
315 pixman_box32_t **outrects)
316{
317 bool merged;
318 pixman_box32_t *out, merge_rect;
319 int i, j, nout;
320
321 if (!nrects) {
322 *outrects = NULL;
323 return 0;
324 }
325
326 /* nrects is an upper bound - we're not too worried about
327 * allocating a little extra
328 */
329 out = malloc(sizeof(pixman_box32_t) * nrects);
330 out[0] = inrects[0];
331 nout = 1;
332 for (i = 1; i < nrects; i++) {
333 for (j = 0; j < nout; j++) {
334 merged = merge_down(&inrects[i], &out[j], &merge_rect);
335 if (merged) {
336 out[j] = merge_rect;
337 break;
338 }
339 }
340 if (!merged) {
341 out[nout] = inrects[i];
342 nout++;
343 }
344 }
345 *outrects = out;
346 return nout;
347}
348
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400349static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500350texture_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400351 pixman_region32_t *surf_region)
352{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500353 struct gl_surface_state *gs = get_surface_state(ev->surface);
354 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400355 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400356 GLfloat *v, inv_width, inv_height;
357 unsigned int *vtxcnt, nvtx = 0;
358 pixman_box32_t *rects, *surf_rects;
Derek Foremanf8180982014-10-16 16:37:02 -0500359 pixman_box32_t *raw_rects;
360 int i, j, k, nrects, nsurf, raw_nrects;
361 bool used_band_compression;
362 raw_rects = pixman_region32_rectangles(region, &raw_nrects);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400363 surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
364
Derek Foremanf8180982014-10-16 16:37:02 -0500365 if (raw_nrects < 4) {
366 used_band_compression = false;
367 nrects = raw_nrects;
368 rects = raw_rects;
369 } else {
370 nrects = compress_bands(raw_rects, raw_nrects, &rects);
371 used_band_compression = true;
372 }
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400373 /* worst case we can have 8 vertices per rect (ie. clipped into
374 * an octagon):
375 */
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400376 v = wl_array_add(&gr->vertices, nrects * nsurf * 8 * 4 * sizeof *v);
377 vtxcnt = wl_array_add(&gr->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400378
Pekka Paalanen68033ac2012-12-04 15:58:15 +0200379 inv_width = 1.0 / gs->pitch;
Alexander Larsson4ea95522013-05-22 14:41:37 +0200380 inv_height = 1.0 / gs->height;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400381
382 for (i = 0; i < nrects; i++) {
383 pixman_box32_t *rect = &rects[i];
384 for (j = 0; j < nsurf; j++) {
385 pixman_box32_t *surf_rect = &surf_rects[j];
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200386 GLfloat sx, sy, bx, by;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400387 GLfloat ex[8], ey[8]; /* edge points in screen space */
388 int n;
389
390 /* The transformed surface, after clipping to the clip region,
391 * can have as many as eight sides, emitted as a triangle-fan.
392 * The first vertex in the triangle fan can be chosen arbitrarily,
393 * since the area is guaranteed to be convex.
394 *
395 * If a corner of the transformed surface falls outside of the
396 * clip region, instead of emitting one vertex for the corner
397 * of the surface, up to two are emitted for two corresponding
398 * intersection point(s) between the surface and the clip region.
399 *
400 * To do this, we first calculate the (up to eight) points that
401 * form the intersection of the clip rect and the transformed
402 * surface.
403 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500404 n = calculate_edges(ev, rect, surf_rect, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400405 if (n < 3)
406 continue;
407
408 /* emit edge points: */
409 for (k = 0; k < n; k++) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500410 weston_view_from_global_float(ev, ex[k], ey[k],
411 &sx, &sy);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400412 /* position: */
413 *(v++) = ex[k];
414 *(v++) = ey[k];
415 /* texcoord: */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500416 weston_surface_to_buffer_float(ev->surface,
417 sx, sy,
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200418 &bx, &by);
419 *(v++) = bx * inv_width;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +0400420 if (gs->y_inverted) {
421 *(v++) = by * inv_height;
422 } else {
423 *(v++) = (gs->height - by) * inv_height;
424 }
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400425 }
426
427 vtxcnt[nvtx++] = n;
428 }
429 }
430
Derek Foremanf8180982014-10-16 16:37:02 -0500431 if (used_band_compression)
432 free(rects);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400433 return nvtx;
434}
435
436static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500437triangle_fan_debug(struct weston_view *view, int first, int count)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400438{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500439 struct weston_compositor *compositor = view->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100440 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400441 int i;
442 GLushort *buffer;
443 GLushort *index;
444 int nelems;
445 static int color_idx = 0;
446 static const GLfloat color[][4] = {
447 { 1.0, 0.0, 0.0, 1.0 },
448 { 0.0, 1.0, 0.0, 1.0 },
449 { 0.0, 0.0, 1.0, 1.0 },
450 { 1.0, 1.0, 1.0, 1.0 },
451 };
452
453 nelems = (count - 1 + count - 2) * 2;
454
455 buffer = malloc(sizeof(GLushort) * nelems);
456 index = buffer;
457
458 for (i = 1; i < count; i++) {
459 *index++ = first;
460 *index++ = first + i;
461 }
462
463 for (i = 2; i < count; i++) {
464 *index++ = first + i - 1;
465 *index++ = first + i;
466 }
467
John Kåre Alsaker40684142012-11-13 19:10:25 +0100468 glUseProgram(gr->solid_shader.program);
469 glUniform4fv(gr->solid_shader.color_uniform, 1,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400470 color[color_idx++ % ARRAY_LENGTH(color)]);
471 glDrawElements(GL_LINES, nelems, GL_UNSIGNED_SHORT, buffer);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100472 glUseProgram(gr->current_shader->program);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400473 free(buffer);
474}
475
476static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500477repaint_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400478 pixman_region32_t *surf_region)
479{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500480 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400481 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400482 GLfloat *v;
483 unsigned int *vtxcnt;
484 int i, first, nfans;
485
486 /* The final region to be painted is the intersection of
487 * 'region' and 'surf_region'. However, 'region' is in the global
488 * coordinates, and 'surf_region' is in the surface-local
489 * coordinates. texture_region() will iterate over all pairs of
490 * rectangles from both regions, compute the intersection
491 * polygon for each pair, and store it as a triangle fan if
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400492 * it has a non-zero area (at least 3 vertices1, actually).
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400493 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500494 nfans = texture_region(ev, region, surf_region);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400495
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400496 v = gr->vertices.data;
497 vtxcnt = gr->vtxcnt.data;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400498
499 /* position: */
500 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
501 glEnableVertexAttribArray(0);
502
503 /* texcoord: */
504 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
505 glEnableVertexAttribArray(1);
506
507 for (i = 0, first = 0; i < nfans; i++) {
508 glDrawArrays(GL_TRIANGLE_FAN, first, vtxcnt[i]);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400509 if (gr->fan_debug)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500510 triangle_fan_debug(ev, first, vtxcnt[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400511 first += vtxcnt[i];
512 }
513
514 glDisableVertexAttribArray(1);
515 glDisableVertexAttribArray(0);
516
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400517 gr->vertices.size = 0;
518 gr->vtxcnt.size = 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400519}
520
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100521static int
522use_output(struct weston_output *output)
523{
524 static int errored;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100525 struct gl_output_state *go = get_output_state(output);
526 struct gl_renderer *gr = get_renderer(output->compositor);
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100527 EGLBoolean ret;
528
529 ret = eglMakeCurrent(gr->egl_display, go->egl_surface,
530 go->egl_surface, gr->egl_context);
531
532 if (ret == EGL_FALSE) {
533 if (errored)
534 return -1;
535 errored = 1;
536 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +0200537 gl_renderer_print_egl_error_state();
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100538 return -1;
539 }
540
541 return 0;
542}
543
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300544static int
545shader_init(struct gl_shader *shader, struct gl_renderer *gr,
546 const char *vertex_source, const char *fragment_source);
547
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400548static void
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300549use_shader(struct gl_renderer *gr, struct gl_shader *shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400550{
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300551 if (!shader->program) {
552 int ret;
553
554 ret = shader_init(shader, gr,
555 shader->vertex_source,
556 shader->fragment_source);
557
558 if (ret < 0)
559 weston_log("warning: failed to compile shader\n");
560 }
561
John Kåre Alsaker40684142012-11-13 19:10:25 +0100562 if (gr->current_shader == shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400563 return;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400564 glUseProgram(shader->program);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100565 gr->current_shader = shader;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400566}
567
568static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100569shader_uniforms(struct gl_shader *shader,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500570 struct weston_view *view,
571 struct weston_output *output)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400572{
573 int i;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500574 struct gl_surface_state *gs = get_surface_state(view->surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400575
576 glUniformMatrix4fv(shader->proj_uniform,
577 1, GL_FALSE, output->matrix.d);
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100578 glUniform4fv(shader->color_uniform, 1, gs->color);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500579 glUniform1f(shader->alpha_uniform, view->alpha);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400580
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100581 for (i = 0; i < gs->num_textures; i++)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400582 glUniform1i(shader->tex_uniforms[i], i);
583}
584
585static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500586draw_view(struct weston_view *ev, struct weston_output *output,
587 pixman_region32_t *damage) /* in global coordinates */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400588{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500589 struct weston_compositor *ec = ev->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100590 struct gl_renderer *gr = get_renderer(ec);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500591 struct gl_surface_state *gs = get_surface_state(ev->surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400592 /* repaint bounding region in global coordinates: */
593 pixman_region32_t repaint;
594 /* non-opaque region in surface coordinates: */
595 pixman_region32_t surface_blend;
596 GLint filter;
597 int i;
598
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +0200599 /* In case of a runtime switch of renderers, we may not have received
600 * an attach for this surface since the switch. In that case we don't
601 * have a valid buffer or a proper shader set up so skip rendering. */
602 if (!gs->shader)
603 return;
604
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400605 pixman_region32_init(&repaint);
606 pixman_region32_intersect(&repaint,
Giulio Camuffo95ec0f92014-07-09 22:12:57 +0300607 &ev->transform.masked_boundingbox, damage);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500608 pixman_region32_subtract(&repaint, &repaint, &ev->clip);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400609
610 if (!pixman_region32_not_empty(&repaint))
611 goto out;
612
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400613 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
614
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400615 if (gr->fan_debug) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100616 use_shader(gr, &gr->solid_shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500617 shader_uniforms(&gr->solid_shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400618 }
619
John Kåre Alsaker40684142012-11-13 19:10:25 +0100620 use_shader(gr, gs->shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500621 shader_uniforms(gs->shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400622
Jason Ekstranda7af7042013-10-12 22:38:11 -0500623 if (ev->transform.enabled || output->zoom.active ||
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200624 output->current_scale != ev->surface->buffer_viewport.buffer.scale)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400625 filter = GL_LINEAR;
626 else
627 filter = GL_NEAREST;
628
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100629 for (i = 0; i < gs->num_textures; i++) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400630 glActiveTexture(GL_TEXTURE0 + i);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100631 glBindTexture(gs->target, gs->textures[i]);
632 glTexParameteri(gs->target, GL_TEXTURE_MIN_FILTER, filter);
633 glTexParameteri(gs->target, GL_TEXTURE_MAG_FILTER, filter);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400634 }
635
636 /* blended region is whole surface minus opaque region: */
637 pixman_region32_init_rect(&surface_blend, 0, 0,
Jason Ekstrand918f2dd2013-12-02 21:01:53 -0600638 ev->surface->width, ev->surface->height);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500639 pixman_region32_subtract(&surface_blend, &surface_blend, &ev->surface->opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400640
Jason Ekstranda7af7042013-10-12 22:38:11 -0500641 /* XXX: Should we be using ev->transform.opaque here? */
642 if (pixman_region32_not_empty(&ev->surface->opaque)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100643 if (gs->shader == &gr->texture_shader_rgba) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400644 /* Special case for RGBA textures with possibly
645 * bad data in alpha channel: use the shader
646 * that forces texture alpha = 1.0.
647 * Xwayland surfaces need this.
648 */
John Kåre Alsaker40684142012-11-13 19:10:25 +0100649 use_shader(gr, &gr->texture_shader_rgbx);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500650 shader_uniforms(&gr->texture_shader_rgbx, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400651 }
652
Jason Ekstranda7af7042013-10-12 22:38:11 -0500653 if (ev->alpha < 1.0)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400654 glEnable(GL_BLEND);
655 else
656 glDisable(GL_BLEND);
657
Jason Ekstranda7af7042013-10-12 22:38:11 -0500658 repaint_region(ev, &repaint, &ev->surface->opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400659 }
660
661 if (pixman_region32_not_empty(&surface_blend)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100662 use_shader(gr, gs->shader);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400663 glEnable(GL_BLEND);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500664 repaint_region(ev, &repaint, &surface_blend);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400665 }
666
667 pixman_region32_fini(&surface_blend);
668
669out:
670 pixman_region32_fini(&repaint);
671}
672
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400673static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500674repaint_views(struct weston_output *output, pixman_region32_t *damage)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400675{
676 struct weston_compositor *compositor = output->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500677 struct weston_view *view;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400678
Jason Ekstranda7af7042013-10-12 22:38:11 -0500679 wl_list_for_each_reverse(view, &compositor->view_list, link)
680 if (view->plane == &compositor->primary_plane)
681 draw_view(view, output, damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400682}
683
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500684static void
Jason Ekstrande5512d42014-02-04 21:36:38 -0600685draw_output_border_texture(struct gl_output_state *go,
686 enum gl_renderer_border_side side,
687 int32_t x, int32_t y,
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500688 int32_t width, int32_t height)
689{
Jason Ekstrande5512d42014-02-04 21:36:38 -0600690 struct gl_border_image *img = &go->borders[side];
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500691 static GLushort indices [] = { 0, 1, 3, 3, 1, 2 };
692
693 if (!img->data) {
694 if (img->tex) {
695 glDeleteTextures(1, &img->tex);
696 img->tex = 0;
697 }
698
699 return;
700 }
701
702 if (!img->tex) {
703 glGenTextures(1, &img->tex);
704 glBindTexture(GL_TEXTURE_2D, img->tex);
705
706 glTexParameteri(GL_TEXTURE_2D,
707 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
708 glTexParameteri(GL_TEXTURE_2D,
709 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
710 glTexParameteri(GL_TEXTURE_2D,
711 GL_TEXTURE_MIN_FILTER, GL_NEAREST);
712 glTexParameteri(GL_TEXTURE_2D,
713 GL_TEXTURE_MAG_FILTER, GL_NEAREST);
714 } else {
715 glBindTexture(GL_TEXTURE_2D, img->tex);
716 }
717
Jason Ekstrande5512d42014-02-04 21:36:38 -0600718 if (go->border_status & (1 << side)) {
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500719#ifdef GL_EXT_unpack_subimage
720 glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0);
721 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
722 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
723#endif
724 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
725 img->tex_width, img->height, 0,
726 GL_BGRA_EXT, GL_UNSIGNED_BYTE, img->data);
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500727 }
728
729 GLfloat texcoord[] = {
730 0.0f, 0.0f,
731 (GLfloat)img->width / (GLfloat)img->tex_width, 0.0f,
732 (GLfloat)img->width / (GLfloat)img->tex_width, 1.0f,
733 0.0f, 1.0f,
734 };
735
736 GLfloat verts[] = {
737 x, y,
738 x + width, y,
739 x + width, y + height,
740 x, y + height
741 };
742
743 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
744 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord);
745 glEnableVertexAttribArray(0);
746 glEnableVertexAttribArray(1);
747
748 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
749
750 glDisableVertexAttribArray(1);
751 glDisableVertexAttribArray(0);
752}
753
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -0600754static int
755output_has_borders(struct weston_output *output)
756{
757 struct gl_output_state *go = get_output_state(output);
758
759 return go->borders[GL_RENDERER_BORDER_TOP].data ||
760 go->borders[GL_RENDERER_BORDER_RIGHT].data ||
761 go->borders[GL_RENDERER_BORDER_BOTTOM].data ||
762 go->borders[GL_RENDERER_BORDER_LEFT].data;
763}
764
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500765static void
Jason Ekstrande5512d42014-02-04 21:36:38 -0600766draw_output_borders(struct weston_output *output,
767 enum gl_border_status border_status)
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500768{
769 struct gl_output_state *go = get_output_state(output);
770 struct gl_renderer *gr = get_renderer(output->compositor);
771 struct gl_shader *shader = &gr->texture_shader_rgba;
Jason Ekstrand00b84282013-10-27 22:24:59 -0500772 struct gl_border_image *top, *bottom, *left, *right;
773 struct weston_matrix matrix;
774 int full_width, full_height;
775
Jason Ekstrande5512d42014-02-04 21:36:38 -0600776 if (border_status == BORDER_STATUS_CLEAN)
777 return; /* Clean. Nothing to do. */
778
Jason Ekstrand00b84282013-10-27 22:24:59 -0500779 top = &go->borders[GL_RENDERER_BORDER_TOP];
780 bottom = &go->borders[GL_RENDERER_BORDER_BOTTOM];
781 left = &go->borders[GL_RENDERER_BORDER_LEFT];
782 right = &go->borders[GL_RENDERER_BORDER_RIGHT];
783
784 full_width = output->current_mode->width + left->width + right->width;
785 full_height = output->current_mode->height + top->height + bottom->height;
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500786
787 glDisable(GL_BLEND);
788 use_shader(gr, shader);
789
Jason Ekstrand00b84282013-10-27 22:24:59 -0500790 glViewport(0, 0, full_width, full_height);
791
792 weston_matrix_init(&matrix);
793 weston_matrix_translate(&matrix, -full_width/2.0, -full_height/2.0, 0);
794 weston_matrix_scale(&matrix, 2.0/full_width, -2.0/full_height, 1);
795 glUniformMatrix4fv(shader->proj_uniform, 1, GL_FALSE, matrix.d);
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500796
797 glUniform1i(shader->tex_uniforms[0], 0);
798 glUniform1f(shader->alpha_uniform, 1);
799 glActiveTexture(GL_TEXTURE0);
800
Jason Ekstrande5512d42014-02-04 21:36:38 -0600801 if (border_status & BORDER_TOP_DIRTY)
802 draw_output_border_texture(go, GL_RENDERER_BORDER_TOP,
803 0, 0,
804 full_width, top->height);
805 if (border_status & BORDER_LEFT_DIRTY)
806 draw_output_border_texture(go, GL_RENDERER_BORDER_LEFT,
807 0, top->height,
808 left->width, output->current_mode->height);
809 if (border_status & BORDER_RIGHT_DIRTY)
810 draw_output_border_texture(go, GL_RENDERER_BORDER_RIGHT,
811 full_width - right->width, top->height,
812 right->width, output->current_mode->height);
813 if (border_status & BORDER_BOTTOM_DIRTY)
814 draw_output_border_texture(go, GL_RENDERER_BORDER_BOTTOM,
815 0, full_height - bottom->height,
816 full_width, bottom->height);
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500817}
John Kåre Alsaker44154502012-11-13 19:10:20 +0100818
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400819static void
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -0600820output_get_border_damage(struct weston_output *output,
821 enum gl_border_status border_status,
822 pixman_region32_t *damage)
823{
824 struct gl_output_state *go = get_output_state(output);
825 struct gl_border_image *top, *bottom, *left, *right;
826 int full_width, full_height;
827
828 if (border_status == BORDER_STATUS_CLEAN)
829 return; /* Clean. Nothing to do. */
830
831 top = &go->borders[GL_RENDERER_BORDER_TOP];
832 bottom = &go->borders[GL_RENDERER_BORDER_BOTTOM];
833 left = &go->borders[GL_RENDERER_BORDER_LEFT];
834 right = &go->borders[GL_RENDERER_BORDER_RIGHT];
835
836 full_width = output->current_mode->width + left->width + right->width;
837 full_height = output->current_mode->height + top->height + bottom->height;
838 if (border_status & BORDER_TOP_DIRTY)
839 pixman_region32_union_rect(damage, damage,
840 0, 0,
841 full_width, top->height);
842 if (border_status & BORDER_LEFT_DIRTY)
843 pixman_region32_union_rect(damage, damage,
844 0, top->height,
845 left->width, output->current_mode->height);
846 if (border_status & BORDER_RIGHT_DIRTY)
847 pixman_region32_union_rect(damage, damage,
848 full_width - right->width, top->height,
849 right->width, output->current_mode->height);
850 if (border_status & BORDER_BOTTOM_DIRTY)
851 pixman_region32_union_rect(damage, damage,
852 0, full_height - bottom->height,
853 full_width, bottom->height);
854}
855
856static void
Jason Ekstrande5512d42014-02-04 21:36:38 -0600857output_get_damage(struct weston_output *output,
858 pixman_region32_t *buffer_damage, uint32_t *border_damage)
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200859{
860 struct gl_output_state *go = get_output_state(output);
861 struct gl_renderer *gr = get_renderer(output->compositor);
862 EGLint buffer_age = 0;
863 EGLBoolean ret;
864 int i;
865
866 if (gr->has_egl_buffer_age) {
867 ret = eglQuerySurface(gr->egl_display, go->egl_surface,
868 EGL_BUFFER_AGE_EXT, &buffer_age);
869 if (ret == EGL_FALSE) {
870 weston_log("buffer age query failed.\n");
871 gl_renderer_print_egl_error_state();
872 }
873 }
874
Jason Ekstrande5512d42014-02-04 21:36:38 -0600875 if (buffer_age == 0 || buffer_age - 1 > BUFFER_DAMAGE_COUNT) {
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200876 pixman_region32_copy(buffer_damage, &output->region);
Jason Ekstrande5512d42014-02-04 21:36:38 -0600877 *border_damage = BORDER_ALL_DIRTY;
878 } else {
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200879 for (i = 0; i < buffer_age - 1; i++)
Derek Foreman4c582662014-10-09 18:39:44 -0500880 *border_damage |= go->border_damage[(go->buffer_damage_index + i) % BUFFER_DAMAGE_COUNT];
Jason Ekstrande5512d42014-02-04 21:36:38 -0600881
882 if (*border_damage & BORDER_SIZE_CHANGED) {
883 /* If we've had a resize, we have to do a full
884 * repaint. */
885 *border_damage |= BORDER_ALL_DIRTY;
886 pixman_region32_copy(buffer_damage, &output->region);
887 } else {
888 for (i = 0; i < buffer_age - 1; i++)
889 pixman_region32_union(buffer_damage,
890 buffer_damage,
Derek Foreman4c582662014-10-09 18:39:44 -0500891 &go->buffer_damage[(go->buffer_damage_index + i) % BUFFER_DAMAGE_COUNT]);
Jason Ekstrande5512d42014-02-04 21:36:38 -0600892 }
893 }
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200894}
895
896static void
897output_rotate_damage(struct weston_output *output,
Jason Ekstrande5512d42014-02-04 21:36:38 -0600898 pixman_region32_t *output_damage,
899 enum gl_border_status border_status)
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200900{
901 struct gl_output_state *go = get_output_state(output);
902 struct gl_renderer *gr = get_renderer(output->compositor);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200903
904 if (!gr->has_egl_buffer_age)
905 return;
906
Derek Foreman4c582662014-10-09 18:39:44 -0500907 go->buffer_damage_index += BUFFER_DAMAGE_COUNT - 1;
908 go->buffer_damage_index %= BUFFER_DAMAGE_COUNT;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200909
Derek Foreman4c582662014-10-09 18:39:44 -0500910 pixman_region32_copy(&go->buffer_damage[go->buffer_damage_index], output_damage);
911 go->border_damage[go->buffer_damage_index] = border_status;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200912}
913
914static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100915gl_renderer_repaint_output(struct weston_output *output,
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400916 pixman_region32_t *output_damage)
917{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100918 struct gl_output_state *go = get_output_state(output);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400919 struct weston_compositor *compositor = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100920 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400921 EGLBoolean ret;
922 static int errored;
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -0600923#ifdef EGL_EXT_swap_buffers_with_damage
924 int i, nrects, buffer_height;
925 EGLint *egl_damage, *d;
926 pixman_box32_t *rects;
927#endif
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200928 pixman_region32_t buffer_damage, total_damage;
Jason Ekstrande5512d42014-02-04 21:36:38 -0600929 enum gl_border_status border_damage = BORDER_STATUS_CLEAN;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400930
Jason Ekstrand00b84282013-10-27 22:24:59 -0500931 /* Calculate the viewport */
932 glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width,
933 go->borders[GL_RENDERER_BORDER_BOTTOM].height,
934 output->current_mode->width,
935 output->current_mode->height);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400936
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100937 if (use_output(output) < 0)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400938 return;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400939
940 /* if debugging, redraw everything outside the damage to clean up
941 * debug lines from the previous draw on this buffer:
942 */
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400943 if (gr->fan_debug) {
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400944 pixman_region32_t undamaged;
945 pixman_region32_init(&undamaged);
946 pixman_region32_subtract(&undamaged, &output->region,
947 output_damage);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400948 gr->fan_debug = 0;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500949 repaint_views(output, &undamaged);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400950 gr->fan_debug = 1;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400951 pixman_region32_fini(&undamaged);
952 }
953
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +0200954 pixman_region32_init(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200955 pixman_region32_init(&buffer_damage);
956
Jason Ekstrande5512d42014-02-04 21:36:38 -0600957 output_get_damage(output, &buffer_damage, &border_damage);
958 output_rotate_damage(output, output_damage, go->border_status);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200959
960 pixman_region32_union(&total_damage, &buffer_damage, output_damage);
Jason Ekstrande5512d42014-02-04 21:36:38 -0600961 border_damage |= go->border_status;
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300962
Jason Ekstranda7af7042013-10-12 22:38:11 -0500963 repaint_views(output, &total_damage);
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +0200964
965 pixman_region32_fini(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200966 pixman_region32_fini(&buffer_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400967
Jason Ekstrande5512d42014-02-04 21:36:38 -0600968 draw_output_borders(output, border_damage);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100969
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +0200970 pixman_region32_copy(&output->previous_damage, output_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400971 wl_signal_emit(&output->frame_signal, output);
972
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -0600973#ifdef EGL_EXT_swap_buffers_with_damage
974 if (gr->swap_buffers_with_damage) {
975 pixman_region32_init(&buffer_damage);
976 weston_transformed_region(output->width, output->height,
977 output->transform,
978 output->current_scale,
979 output_damage, &buffer_damage);
980
981 if (output_has_borders(output)) {
982 pixman_region32_translate(&buffer_damage,
983 go->borders[GL_RENDERER_BORDER_LEFT].width,
984 go->borders[GL_RENDERER_BORDER_TOP].height);
985 output_get_border_damage(output, go->border_status,
986 &buffer_damage);
987 }
988
989 rects = pixman_region32_rectangles(&buffer_damage, &nrects);
990 egl_damage = malloc(nrects * 4 * sizeof(EGLint));
991
992 buffer_height = go->borders[GL_RENDERER_BORDER_TOP].height +
993 output->current_mode->height +
994 go->borders[GL_RENDERER_BORDER_BOTTOM].height;
995
996 d = egl_damage;
997 for (i = 0; i < nrects; ++i) {
998 *d++ = rects[i].x1;
999 *d++ = buffer_height - rects[i].y2;
1000 *d++ = rects[i].x2 - rects[i].x1;
1001 *d++ = rects[i].y2 - rects[i].y1;
1002 }
1003 ret = gr->swap_buffers_with_damage(gr->egl_display,
1004 go->egl_surface,
1005 egl_damage, nrects);
1006 free(egl_damage);
1007 pixman_region32_fini(&buffer_damage);
1008 } else {
1009 ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
1010 }
1011#else /* ! defined EGL_EXT_swap_buffers_with_damage */
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001012 ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -06001013#endif
1014
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001015 if (ret == EGL_FALSE && !errored) {
1016 errored = 1;
1017 weston_log("Failed in eglSwapBuffers.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001018 gl_renderer_print_egl_error_state();
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001019 }
1020
Jason Ekstrande5512d42014-02-04 21:36:38 -06001021 go->border_status = BORDER_STATUS_CLEAN;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001022}
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001023
John Kåre Alsakera95b2d62012-11-13 19:10:21 +01001024static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001025gl_renderer_read_pixels(struct weston_output *output,
John Kåre Alsakera95b2d62012-11-13 19:10:21 +01001026 pixman_format_code_t format, void *pixels,
1027 uint32_t x, uint32_t y,
1028 uint32_t width, uint32_t height)
1029{
1030 GLenum gl_format;
Jason Ekstrand701f6362014-04-02 19:53:59 -05001031 struct gl_output_state *go = get_output_state(output);
1032
1033 x += go->borders[GL_RENDERER_BORDER_LEFT].width;
1034 y += go->borders[GL_RENDERER_BORDER_BOTTOM].height;
John Kåre Alsakera95b2d62012-11-13 19:10:21 +01001035
1036 switch (format) {
1037 case PIXMAN_a8r8g8b8:
1038 gl_format = GL_BGRA_EXT;
1039 break;
1040 case PIXMAN_a8b8g8r8:
1041 gl_format = GL_RGBA;
1042 break;
1043 default:
1044 return -1;
1045 }
1046
1047 if (use_output(output) < 0)
1048 return -1;
1049
1050 glPixelStorei(GL_PACK_ALIGNMENT, 1);
1051 glReadPixels(x, y, width, height, gl_format,
1052 GL_UNSIGNED_BYTE, pixels);
1053
1054 return 0;
1055}
1056
Kristian Høgsbergfa1be022012-09-05 22:49:55 -04001057static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001058gl_renderer_flush_damage(struct weston_surface *surface)
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001059{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001060 struct gl_renderer *gr = get_renderer(surface->compositor);
1061 struct gl_surface_state *gs = get_surface_state(surface);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001062 struct weston_buffer *buffer = gs->buffer_ref.buffer;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001063 struct weston_view *view;
1064 int texture_used;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001065
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -07001066#ifdef GL_EXT_unpack_subimage
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001067 pixman_box32_t *rectangles;
1068 void *data;
1069 int i, n;
1070#endif
1071
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001072 pixman_region32_union(&gs->texture_damage,
1073 &gs->texture_damage, &surface->damage);
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001074
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001075 if (!buffer)
1076 return;
1077
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001078 /* Avoid upload, if the texture won't be used this time.
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001079 * We still accumulate the damage in texture_damage, and
1080 * hold the reference to the buffer, in case the surface
1081 * migrates back to the primary plane.
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001082 */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001083 texture_used = 0;
1084 wl_list_for_each(view, &surface->views, surface_link) {
1085 if (view->plane == &surface->compositor->primary_plane) {
1086 texture_used = 1;
1087 break;
1088 }
1089 }
1090 if (!texture_used)
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001091 return;
1092
Ander Conselvan de Oliveira895b1fd2013-11-19 15:22:05 +02001093 if (!pixman_region32_not_empty(&gs->texture_damage) &&
1094 !gs->needs_full_upload)
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001095 goto done;
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001096
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001097 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001098
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001099 if (!gr->has_unpack_subimage) {
Neil Robertse5051712013-11-13 15:44:06 +00001100 wl_shm_buffer_begin_access(buffer->shm_buffer);
Neil Roberts4d085e72014-04-07 15:01:01 +01001101 glTexImage2D(GL_TEXTURE_2D, 0, gs->gl_format,
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001102 gs->pitch, buffer->height, 0,
Neil Roberts4d085e72014-04-07 15:01:01 +01001103 gs->gl_format, gs->gl_pixel_type,
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001104 wl_shm_buffer_get_data(buffer->shm_buffer));
Neil Robertse5051712013-11-13 15:44:06 +00001105 wl_shm_buffer_end_access(buffer->shm_buffer);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001106
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001107 goto done;
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001108 }
1109
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -07001110#ifdef GL_EXT_unpack_subimage
1111 glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, gs->pitch);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001112 data = wl_shm_buffer_get_data(buffer->shm_buffer);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +03001113
1114 if (gs->needs_full_upload) {
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -07001115 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
1116 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
Neil Robertse5051712013-11-13 15:44:06 +00001117 wl_shm_buffer_begin_access(buffer->shm_buffer);
Neil Roberts4d085e72014-04-07 15:01:01 +01001118 glTexImage2D(GL_TEXTURE_2D, 0, gs->gl_format,
Neil Roberts39a443f2014-04-04 16:24:54 +01001119 gs->pitch, buffer->height, 0,
Neil Roberts4d085e72014-04-07 15:01:01 +01001120 gs->gl_format, gs->gl_pixel_type, data);
Neil Robertse5051712013-11-13 15:44:06 +00001121 wl_shm_buffer_end_access(buffer->shm_buffer);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +03001122 goto done;
1123 }
1124
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001125 rectangles = pixman_region32_rectangles(&gs->texture_damage, &n);
Neil Robertse5051712013-11-13 15:44:06 +00001126 wl_shm_buffer_begin_access(buffer->shm_buffer);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001127 for (i = 0; i < n; i++) {
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +02001128 pixman_box32_t r;
1129
1130 r = weston_surface_to_buffer_rect(surface, rectangles[i]);
1131
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -07001132 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, r.x1);
1133 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, r.y1);
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +02001134 glTexSubImage2D(GL_TEXTURE_2D, 0, r.x1, r.y1,
1135 r.x2 - r.x1, r.y2 - r.y1,
Neil Roberts4d085e72014-04-07 15:01:01 +01001136 gs->gl_format, gs->gl_pixel_type, data);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001137 }
Neil Robertse5051712013-11-13 15:44:06 +00001138 wl_shm_buffer_end_access(buffer->shm_buffer);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001139#endif
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001140
1141done:
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001142 pixman_region32_fini(&gs->texture_damage);
1143 pixman_region32_init(&gs->texture_damage);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +03001144 gs->needs_full_upload = 0;
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001145
1146 weston_buffer_reference(&gs->buffer_ref, NULL);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001147}
1148
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001149static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001150ensure_textures(struct gl_surface_state *gs, int num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001151{
1152 int i;
1153
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001154 if (num_textures <= gs->num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001155 return;
1156
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001157 for (i = gs->num_textures; i < num_textures; i++) {
1158 glGenTextures(1, &gs->textures[i]);
1159 glBindTexture(gs->target, gs->textures[i]);
1160 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001161 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001162 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001163 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1164 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001165 gs->num_textures = num_textures;
1166 glBindTexture(gs->target, 0);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001167}
1168
Kristian Høgsbergfa1be022012-09-05 22:49:55 -04001169static void
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001170gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
1171 struct wl_shm_buffer *shm_buffer)
1172{
1173 struct weston_compositor *ec = es->compositor;
1174 struct gl_renderer *gr = get_renderer(ec);
1175 struct gl_surface_state *gs = get_surface_state(es);
Neil Roberts4d085e72014-04-07 15:01:01 +01001176 GLenum gl_format, gl_pixel_type;
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001177 int pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001178
1179 buffer->shm_buffer = shm_buffer;
1180 buffer->width = wl_shm_buffer_get_width(shm_buffer);
1181 buffer->height = wl_shm_buffer_get_height(shm_buffer);
1182
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001183 switch (wl_shm_buffer_get_format(shm_buffer)) {
1184 case WL_SHM_FORMAT_XRGB8888:
1185 gs->shader = &gr->texture_shader_rgbx;
1186 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
Neil Roberts4d085e72014-04-07 15:01:01 +01001187 gl_format = GL_BGRA_EXT;
1188 gl_pixel_type = GL_UNSIGNED_BYTE;
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001189 break;
1190 case WL_SHM_FORMAT_ARGB8888:
1191 gs->shader = &gr->texture_shader_rgba;
1192 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
Neil Roberts4d085e72014-04-07 15:01:01 +01001193 gl_format = GL_BGRA_EXT;
1194 gl_pixel_type = GL_UNSIGNED_BYTE;
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001195 break;
1196 case WL_SHM_FORMAT_RGB565:
1197 gs->shader = &gr->texture_shader_rgbx;
1198 pitch = wl_shm_buffer_get_stride(shm_buffer) / 2;
Neil Roberts4d085e72014-04-07 15:01:01 +01001199 gl_format = GL_RGB;
1200 gl_pixel_type = GL_UNSIGNED_SHORT_5_6_5;
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001201 break;
1202 default:
Neil Roberts4d085e72014-04-07 15:01:01 +01001203 weston_log("warning: unknown shm buffer format: %08x\n",
1204 wl_shm_buffer_get_format(shm_buffer));
1205 return;
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001206 }
1207
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001208 /* Only allocate a texture if it doesn't match existing one.
1209 * If a switch from DRM allocated buffer to a SHM buffer is
1210 * happening, we need to allocate a new texture buffer. */
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001211 if (pitch != gs->pitch ||
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001212 buffer->height != gs->height ||
Neil Roberts4d085e72014-04-07 15:01:01 +01001213 gl_format != gs->gl_format ||
1214 gl_pixel_type != gs->gl_pixel_type ||
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001215 gs->buffer_type != BUFFER_TYPE_SHM) {
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001216 gs->pitch = pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001217 gs->height = buffer->height;
1218 gs->target = GL_TEXTURE_2D;
Neil Roberts4d085e72014-04-07 15:01:01 +01001219 gs->gl_format = gl_format;
1220 gs->gl_pixel_type = gl_pixel_type;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001221 gs->buffer_type = BUFFER_TYPE_SHM;
1222 gs->needs_full_upload = 1;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001223 gs->y_inverted = 1;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001224
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001225 gs->surface = es;
1226
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001227 ensure_textures(gs, 1);
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001228 }
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001229}
1230
1231static void
1232gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
1233 uint32_t format)
1234{
1235 struct weston_compositor *ec = es->compositor;
1236 struct gl_renderer *gr = get_renderer(ec);
1237 struct gl_surface_state *gs = get_surface_state(es);
1238 EGLint attribs[3];
1239 int i, num_planes;
1240
1241 buffer->legacy_buffer = (struct wl_buffer *)buffer->resource;
1242 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1243 EGL_WIDTH, &buffer->width);
1244 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1245 EGL_HEIGHT, &buffer->height);
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001246 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1247 EGL_WAYLAND_Y_INVERTED_WL, &buffer->y_inverted);
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001248
1249 for (i = 0; i < gs->num_images; i++)
1250 gr->destroy_image(gr->egl_display, gs->images[i]);
1251 gs->num_images = 0;
1252 gs->target = GL_TEXTURE_2D;
1253 switch (format) {
1254 case EGL_TEXTURE_RGB:
1255 case EGL_TEXTURE_RGBA:
1256 default:
1257 num_planes = 1;
1258 gs->shader = &gr->texture_shader_rgba;
1259 break;
1260 case EGL_TEXTURE_EXTERNAL_WL:
1261 num_planes = 1;
1262 gs->target = GL_TEXTURE_EXTERNAL_OES;
1263 gs->shader = &gr->texture_shader_egl_external;
1264 break;
1265 case EGL_TEXTURE_Y_UV_WL:
1266 num_planes = 2;
1267 gs->shader = &gr->texture_shader_y_uv;
1268 break;
1269 case EGL_TEXTURE_Y_U_V_WL:
1270 num_planes = 3;
1271 gs->shader = &gr->texture_shader_y_u_v;
1272 break;
1273 case EGL_TEXTURE_Y_XUXV_WL:
1274 num_planes = 2;
1275 gs->shader = &gr->texture_shader_y_xuxv;
1276 break;
1277 }
1278
1279 ensure_textures(gs, num_planes);
1280 for (i = 0; i < num_planes; i++) {
1281 attribs[0] = EGL_WAYLAND_PLANE_WL;
1282 attribs[1] = i;
1283 attribs[2] = EGL_NONE;
1284 gs->images[i] = gr->create_image(gr->egl_display,
1285 NULL,
1286 EGL_WAYLAND_BUFFER_WL,
1287 buffer->legacy_buffer,
1288 attribs);
1289 if (!gs->images[i]) {
1290 weston_log("failed to create img for plane %d\n", i);
1291 continue;
1292 }
1293 gs->num_images++;
1294
1295 glActiveTexture(GL_TEXTURE0 + i);
1296 glBindTexture(gs->target, gs->textures[i]);
1297 gr->image_target_texture_2d(gs->target,
1298 gs->images[i]);
1299 }
1300
1301 gs->pitch = buffer->width;
1302 gs->height = buffer->height;
1303 gs->buffer_type = BUFFER_TYPE_EGL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001304 gs->y_inverted = buffer->y_inverted;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001305}
1306
1307static void
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001308gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001309{
1310 struct weston_compositor *ec = es->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001311 struct gl_renderer *gr = get_renderer(ec);
1312 struct gl_surface_state *gs = get_surface_state(es);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001313 struct wl_shm_buffer *shm_buffer;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001314 EGLint format;
1315 int i;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001316
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001317 weston_buffer_reference(&gs->buffer_ref, buffer);
1318
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001319 if (!buffer) {
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001320 for (i = 0; i < gs->num_images; i++) {
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001321 gr->destroy_image(gr->egl_display, gs->images[i]);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001322 gs->images[i] = NULL;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001323 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001324 gs->num_images = 0;
1325 glDeleteTextures(gs->num_textures, gs->textures);
1326 gs->num_textures = 0;
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001327 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001328 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001329 return;
1330 }
1331
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001332 shm_buffer = wl_shm_buffer_get(buffer->resource);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001333
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001334 if (shm_buffer)
1335 gl_renderer_attach_shm(es, buffer, shm_buffer);
Kristian Høgsberg47229392013-08-07 11:59:54 -07001336 else if (gr->query_buffer(gr->egl_display, (void *) buffer->resource,
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001337 EGL_TEXTURE_FORMAT, &format))
1338 gl_renderer_attach_egl(es, buffer, format);
1339 else {
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001340 weston_log("unhandled buffer type!\n");
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001341 weston_buffer_reference(&gs->buffer_ref, NULL);
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001342 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001343 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001344 }
1345}
1346
Kristian Høgsberg42263852012-09-06 21:59:29 -04001347static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001348gl_renderer_surface_set_color(struct weston_surface *surface,
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001349 float red, float green, float blue, float alpha)
1350{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001351 struct gl_surface_state *gs = get_surface_state(surface);
1352 struct gl_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001353
1354 gs->color[0] = red;
1355 gs->color[1] = green;
1356 gs->color[2] = blue;
1357 gs->color[3] = alpha;
1358
John Kåre Alsaker40684142012-11-13 19:10:25 +01001359 gs->shader = &gr->solid_shader;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001360}
1361
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001362static void
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001363surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr)
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001364{
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001365 int i;
1366
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001367 wl_list_remove(&gs->surface_destroy_listener.link);
1368 wl_list_remove(&gs->renderer_destroy_listener.link);
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001369
1370 gs->surface->renderer_state = NULL;
1371
1372 glDeleteTextures(gs->num_textures, gs->textures);
1373
1374 for (i = 0; i < gs->num_images; i++)
1375 gr->destroy_image(gr->egl_display, gs->images[i]);
1376
1377 weston_buffer_reference(&gs->buffer_ref, NULL);
1378 pixman_region32_fini(&gs->texture_damage);
1379 free(gs);
1380}
1381
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001382static void
1383surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
1384{
1385 struct gl_surface_state *gs;
1386 struct gl_renderer *gr;
1387
1388 gs = container_of(listener, struct gl_surface_state,
1389 surface_destroy_listener);
1390
1391 gr = get_renderer(gs->surface->compositor);
1392
1393 surface_state_destroy(gs, gr);
1394}
1395
1396static void
1397surface_state_handle_renderer_destroy(struct wl_listener *listener, void *data)
1398{
1399 struct gl_surface_state *gs;
1400 struct gl_renderer *gr;
1401
1402 gr = data;
1403
1404 gs = container_of(listener, struct gl_surface_state,
1405 renderer_destroy_listener);
1406
1407 surface_state_destroy(gs, gr);
1408}
1409
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001410static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001411gl_renderer_create_surface(struct weston_surface *surface)
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001412{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001413 struct gl_surface_state *gs;
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001414 struct gl_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001415
1416 gs = calloc(1, sizeof *gs);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001417 if (!gs)
1418 return -1;
1419
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001420 /* A buffer is never attached to solid color surfaces, yet
1421 * they still go through texcoord computations. Do not divide
1422 * by zero there.
1423 */
1424 gs->pitch = 1;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001425 gs->y_inverted = 1;
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001426
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001427 gs->surface = surface;
1428
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001429 pixman_region32_init(&gs->texture_damage);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001430 surface->renderer_state = gs;
1431
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001432 gs->surface_destroy_listener.notify =
1433 surface_state_handle_surface_destroy;
1434 wl_signal_add(&surface->destroy_signal,
1435 &gs->surface_destroy_listener);
1436
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001437 gs->renderer_destroy_listener.notify =
1438 surface_state_handle_renderer_destroy;
1439 wl_signal_add(&gr->destroy_signal,
1440 &gs->renderer_destroy_listener);
1441
Ander Conselvan de Oliveira895b1fd2013-11-19 15:22:05 +02001442 if (surface->buffer_ref.buffer) {
1443 gl_renderer_attach(surface, surface->buffer_ref.buffer);
1444 gl_renderer_flush_damage(surface);
1445 }
1446
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001447 return 0;
1448}
1449
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001450static const char vertex_shader[] =
1451 "uniform mat4 proj;\n"
1452 "attribute vec2 position;\n"
1453 "attribute vec2 texcoord;\n"
1454 "varying vec2 v_texcoord;\n"
1455 "void main()\n"
1456 "{\n"
1457 " gl_Position = proj * vec4(position, 0.0, 1.0);\n"
1458 " v_texcoord = texcoord;\n"
1459 "}\n";
1460
1461/* Declare common fragment shader uniforms */
1462#define FRAGMENT_CONVERT_YUV \
1463 " y *= alpha;\n" \
1464 " u *= alpha;\n" \
1465 " v *= alpha;\n" \
1466 " gl_FragColor.r = y + 1.59602678 * v;\n" \
1467 " gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n" \
1468 " gl_FragColor.b = y + 2.01723214 * u;\n" \
1469 " gl_FragColor.a = alpha;\n"
1470
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001471static const char fragment_debug[] =
1472 " gl_FragColor = vec4(0.0, 0.3, 0.0, 0.2) + gl_FragColor * 0.8;\n";
1473
1474static const char fragment_brace[] =
1475 "}\n";
1476
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001477static const char texture_fragment_shader_rgba[] =
1478 "precision mediump float;\n"
1479 "varying vec2 v_texcoord;\n"
1480 "uniform sampler2D tex;\n"
1481 "uniform float alpha;\n"
1482 "void main()\n"
1483 "{\n"
1484 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001485 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001486
1487static const char texture_fragment_shader_rgbx[] =
1488 "precision mediump float;\n"
1489 "varying vec2 v_texcoord;\n"
1490 "uniform sampler2D tex;\n"
1491 "uniform float alpha;\n"
1492 "void main()\n"
1493 "{\n"
1494 " gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb\n;"
1495 " gl_FragColor.a = alpha;\n"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001496 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001497
1498static const char texture_fragment_shader_egl_external[] =
1499 "#extension GL_OES_EGL_image_external : require\n"
1500 "precision mediump float;\n"
1501 "varying vec2 v_texcoord;\n"
1502 "uniform samplerExternalOES tex;\n"
1503 "uniform float alpha;\n"
1504 "void main()\n"
1505 "{\n"
1506 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001507 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001508
1509static const char texture_fragment_shader_y_uv[] =
1510 "precision mediump float;\n"
1511 "uniform sampler2D tex;\n"
1512 "uniform sampler2D tex1;\n"
1513 "varying vec2 v_texcoord;\n"
1514 "uniform float alpha;\n"
1515 "void main() {\n"
1516 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1517 " float u = texture2D(tex1, v_texcoord).r - 0.5;\n"
1518 " float v = texture2D(tex1, v_texcoord).g - 0.5;\n"
1519 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001520 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001521
1522static const char texture_fragment_shader_y_u_v[] =
1523 "precision mediump float;\n"
1524 "uniform sampler2D tex;\n"
1525 "uniform sampler2D tex1;\n"
1526 "uniform sampler2D tex2;\n"
1527 "varying vec2 v_texcoord;\n"
1528 "uniform float alpha;\n"
1529 "void main() {\n"
1530 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1531 " float u = texture2D(tex1, v_texcoord).x - 0.5;\n"
1532 " float v = texture2D(tex2, v_texcoord).x - 0.5;\n"
1533 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001534 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001535
1536static const char texture_fragment_shader_y_xuxv[] =
1537 "precision mediump float;\n"
1538 "uniform sampler2D tex;\n"
1539 "uniform sampler2D tex1;\n"
1540 "varying vec2 v_texcoord;\n"
1541 "uniform float alpha;\n"
1542 "void main() {\n"
1543 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1544 " float u = texture2D(tex1, v_texcoord).g - 0.5;\n"
1545 " float v = texture2D(tex1, v_texcoord).a - 0.5;\n"
1546 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001547 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001548
1549static const char solid_fragment_shader[] =
1550 "precision mediump float;\n"
1551 "uniform vec4 color;\n"
1552 "uniform float alpha;\n"
1553 "void main()\n"
1554 "{\n"
1555 " gl_FragColor = alpha * color\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001556 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001557
1558static int
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001559compile_shader(GLenum type, int count, const char **sources)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001560{
1561 GLuint s;
1562 char msg[512];
1563 GLint status;
1564
1565 s = glCreateShader(type);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001566 glShaderSource(s, count, sources, NULL);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001567 glCompileShader(s);
1568 glGetShaderiv(s, GL_COMPILE_STATUS, &status);
1569 if (!status) {
1570 glGetShaderInfoLog(s, sizeof msg, NULL, msg);
1571 weston_log("shader info: %s\n", msg);
1572 return GL_NONE;
1573 }
1574
1575 return s;
1576}
1577
1578static int
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03001579shader_init(struct gl_shader *shader, struct gl_renderer *renderer,
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001580 const char *vertex_source, const char *fragment_source)
1581{
1582 char msg[512];
1583 GLint status;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001584 int count;
1585 const char *sources[3];
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001586
1587 shader->vertex_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001588 compile_shader(GL_VERTEX_SHADER, 1, &vertex_source);
1589
1590 if (renderer->fragment_shader_debug) {
1591 sources[0] = fragment_source;
1592 sources[1] = fragment_debug;
1593 sources[2] = fragment_brace;
1594 count = 3;
1595 } else {
1596 sources[0] = fragment_source;
1597 sources[1] = fragment_brace;
1598 count = 2;
1599 }
1600
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001601 shader->fragment_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001602 compile_shader(GL_FRAGMENT_SHADER, count, sources);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001603
1604 shader->program = glCreateProgram();
1605 glAttachShader(shader->program, shader->vertex_shader);
1606 glAttachShader(shader->program, shader->fragment_shader);
1607 glBindAttribLocation(shader->program, 0, "position");
1608 glBindAttribLocation(shader->program, 1, "texcoord");
1609
1610 glLinkProgram(shader->program);
1611 glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
1612 if (!status) {
1613 glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
1614 weston_log("link info: %s\n", msg);
1615 return -1;
1616 }
1617
1618 shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
1619 shader->tex_uniforms[0] = glGetUniformLocation(shader->program, "tex");
1620 shader->tex_uniforms[1] = glGetUniformLocation(shader->program, "tex1");
1621 shader->tex_uniforms[2] = glGetUniformLocation(shader->program, "tex2");
1622 shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
1623 shader->color_uniform = glGetUniformLocation(shader->program, "color");
1624
1625 return 0;
1626}
1627
1628static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001629shader_release(struct gl_shader *shader)
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001630{
1631 glDeleteShader(shader->vertex_shader);
1632 glDeleteShader(shader->fragment_shader);
1633 glDeleteProgram(shader->program);
1634
1635 shader->vertex_shader = 0;
1636 shader->fragment_shader = 0;
1637 shader->program = 0;
1638}
1639
1640static void
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001641log_extensions(const char *name, const char *extensions)
1642{
1643 const char *p, *end;
1644 int l;
1645 int len;
1646
1647 l = weston_log("%s:", name);
1648 p = extensions;
1649 while (*p) {
1650 end = strchrnul(p, ' ');
1651 len = end - p;
1652 if (l + len > 78)
1653 l = weston_log_continue("\n" STAMP_SPACE "%.*s",
1654 len, p);
1655 else
1656 l += weston_log_continue(" %.*s", len, p);
1657 for (p = end; isspace(*p); p++)
1658 ;
1659 }
1660 weston_log_continue("\n");
1661}
1662
1663static void
1664log_egl_gl_info(EGLDisplay egldpy)
1665{
1666 const char *str;
1667
1668 str = eglQueryString(egldpy, EGL_VERSION);
1669 weston_log("EGL version: %s\n", str ? str : "(null)");
1670
1671 str = eglQueryString(egldpy, EGL_VENDOR);
1672 weston_log("EGL vendor: %s\n", str ? str : "(null)");
1673
1674 str = eglQueryString(egldpy, EGL_CLIENT_APIS);
1675 weston_log("EGL client APIs: %s\n", str ? str : "(null)");
1676
1677 str = eglQueryString(egldpy, EGL_EXTENSIONS);
1678 log_extensions("EGL extensions", str ? str : "(null)");
1679
1680 str = (char *)glGetString(GL_VERSION);
1681 weston_log("GL version: %s\n", str ? str : "(null)");
1682
1683 str = (char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
1684 weston_log("GLSL version: %s\n", str ? str : "(null)");
1685
1686 str = (char *)glGetString(GL_VENDOR);
1687 weston_log("GL vendor: %s\n", str ? str : "(null)");
1688
1689 str = (char *)glGetString(GL_RENDERER);
1690 weston_log("GL renderer: %s\n", str ? str : "(null)");
1691
1692 str = (char *)glGetString(GL_EXTENSIONS);
1693 log_extensions("GL extensions", str ? str : "(null)");
1694}
1695
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001696static void
1697log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
1698{
1699 EGLint r, g, b, a;
1700
1701 weston_log("Chosen EGL config details:\n");
1702
1703 weston_log_continue(STAMP_SPACE "RGBA bits");
1704 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_RED_SIZE, &r) &&
1705 eglGetConfigAttrib(egldpy, eglconfig, EGL_GREEN_SIZE, &g) &&
1706 eglGetConfigAttrib(egldpy, eglconfig, EGL_BLUE_SIZE, &b) &&
1707 eglGetConfigAttrib(egldpy, eglconfig, EGL_ALPHA_SIZE, &a))
1708 weston_log_continue(": %d %d %d %d\n", r, g, b, a);
1709 else
1710 weston_log_continue(" unknown\n");
1711
1712 weston_log_continue(STAMP_SPACE "swap interval range");
1713 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_MIN_SWAP_INTERVAL, &a) &&
1714 eglGetConfigAttrib(egldpy, eglconfig, EGL_MAX_SWAP_INTERVAL, &b))
1715 weston_log_continue(": %d - %d\n", a, b);
1716 else
1717 weston_log_continue(" unknown\n");
1718}
1719
Neil Roberts77c1a5b2014-03-07 18:05:50 +00001720static int
1721egl_choose_config(struct gl_renderer *gr, const EGLint *attribs,
1722 const EGLint *visual_id,
1723 EGLConfig *config_out)
1724{
1725 EGLint count = 0;
1726 EGLint matched = 0;
1727 EGLConfig *configs;
1728 int i;
1729
1730 if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1)
1731 return -1;
1732
1733 configs = calloc(count, sizeof *configs);
1734 if (!configs)
1735 return -1;
1736
1737 if (!eglChooseConfig(gr->egl_display, attribs, configs,
1738 count, &matched))
1739 goto out;
1740
1741 for (i = 0; i < matched; ++i) {
1742 EGLint id;
1743
1744 if (visual_id) {
1745 if (!eglGetConfigAttrib(gr->egl_display,
1746 configs[i], EGL_NATIVE_VISUAL_ID,
1747 &id))
1748 continue;
1749
1750 if (id != 0 && id != *visual_id)
1751 continue;
1752 }
1753
1754 *config_out = configs[i];
1755
1756 free(configs);
1757 return 0;
1758 }
1759
1760out:
1761 free(configs);
1762 return -1;
1763}
1764
John Kåre Alsaker44154502012-11-13 19:10:20 +01001765static void
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05001766gl_renderer_output_set_border(struct weston_output *output,
1767 enum gl_renderer_border_side side,
1768 int32_t width, int32_t height,
1769 int32_t tex_width, unsigned char *data)
1770{
1771 struct gl_output_state *go = get_output_state(output);
1772
Jason Ekstrande5512d42014-02-04 21:36:38 -06001773 if (go->borders[side].width != width ||
1774 go->borders[side].height != height)
1775 /* In this case, we have to blow everything and do a full
1776 * repaint. */
1777 go->border_status |= BORDER_SIZE_CHANGED | BORDER_ALL_DIRTY;
1778
1779 if (data == NULL) {
1780 width = 0;
1781 height = 0;
1782 }
1783
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05001784 go->borders[side].width = width;
1785 go->borders[side].height = height;
1786 go->borders[side].tex_width = tex_width;
1787 go->borders[side].data = data;
Jason Ekstrande5512d42014-02-04 21:36:38 -06001788 go->border_status |= 1 << side;
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05001789}
1790
John Kåre Alsaker94659272012-11-13 19:10:18 +01001791static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001792gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001793
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001794static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001795gl_renderer_output_create(struct weston_output *output,
Neil Roberts77c1a5b2014-03-07 18:05:50 +00001796 EGLNativeWindowType window,
1797 const EGLint *attribs,
1798 const EGLint *visual_id)
John Kåre Alsaker94659272012-11-13 19:10:18 +01001799{
1800 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001801 struct gl_renderer *gr = get_renderer(ec);
Neil Roberts77c1a5b2014-03-07 18:05:50 +00001802 struct gl_output_state *go;
1803 EGLConfig egl_config;
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001804 int i;
John Kåre Alsaker94659272012-11-13 19:10:18 +01001805
Neil Roberts77c1a5b2014-03-07 18:05:50 +00001806 if (egl_choose_config(gr, attribs, visual_id, &egl_config) == -1) {
1807 weston_log("failed to choose EGL config for output\n");
1808 return -1;
1809 }
1810
1811 if (egl_config != gr->egl_config &&
1812 !gr->has_configless_context) {
1813 weston_log("attempted to use a different EGL config for an "
1814 "output but EGL_MESA_configless_context is not "
1815 "supported\n");
1816 return -1;
1817 }
1818
1819 go = calloc(1, sizeof *go);
1820
John Kåre Alsaker94659272012-11-13 19:10:18 +01001821 if (!go)
1822 return -1;
1823
1824 go->egl_surface =
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001825 eglCreateWindowSurface(gr->egl_display,
Neil Roberts77c1a5b2014-03-07 18:05:50 +00001826 egl_config,
John Kåre Alsaker94659272012-11-13 19:10:18 +01001827 window, NULL);
1828
1829 if (go->egl_surface == EGL_NO_SURFACE) {
1830 weston_log("failed to create egl surface\n");
1831 free(go);
1832 return -1;
1833 }
1834
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001835 if (gr->egl_context == NULL)
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001836 if (gl_renderer_setup(ec, go->egl_surface) < 0) {
John Kåre Alsaker94659272012-11-13 19:10:18 +01001837 free(go);
1838 return -1;
1839 }
1840
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001841 for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001842 pixman_region32_init(&go->buffer_damage[i]);
1843
Derek Foreman4c582662014-10-09 18:39:44 -05001844 go->buffer_damage_index = 0;
1845
John Kåre Alsaker94659272012-11-13 19:10:18 +01001846 output->renderer_state = go;
1847
Neil Roberts77c1a5b2014-03-07 18:05:50 +00001848 log_egl_config_info(gr->egl_display, egl_config);
1849
John Kåre Alsaker94659272012-11-13 19:10:18 +01001850 return 0;
1851}
1852
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001853static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001854gl_renderer_output_destroy(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01001855{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001856 struct gl_renderer *gr = get_renderer(output->compositor);
1857 struct gl_output_state *go = get_output_state(output);
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001858 int i;
1859
1860 for (i = 0; i < 2; i++)
1861 pixman_region32_fini(&go->buffer_damage[i]);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001862
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001863 eglDestroySurface(gr->egl_display, go->egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001864
1865 free(go);
1866}
1867
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001868static EGLSurface
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001869gl_renderer_output_surface(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01001870{
1871 return get_output_state(output)->egl_surface;
1872}
1873
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03001874static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001875gl_renderer_destroy(struct weston_compositor *ec)
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001876{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001877 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001878
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001879 wl_signal_emit(&gr->destroy_signal, gr);
1880
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001881 if (gr->has_bind_display)
1882 gr->unbind_display(gr->egl_display, ec->wl_display);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001883
1884 /* Work around crash in egl_dri2.c's dri2_make_current() - when does this apply? */
1885 eglMakeCurrent(gr->egl_display,
1886 EGL_NO_SURFACE, EGL_NO_SURFACE,
1887 EGL_NO_CONTEXT);
1888
1889 eglTerminate(gr->egl_display);
1890 eglReleaseThread();
Scott Moreau976a0502013-03-07 10:15:17 -07001891
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -04001892 wl_array_release(&gr->vertices);
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -04001893 wl_array_release(&gr->vtxcnt);
1894
Mariusz Ceiercbb91582014-02-08 20:11:24 +01001895 if (gr->fragment_binding)
1896 weston_binding_destroy(gr->fragment_binding);
1897 if (gr->fan_binding)
1898 weston_binding_destroy(gr->fan_binding);
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +03001899
Scott Moreau976a0502013-03-07 10:15:17 -07001900 free(gr);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001901}
1902
1903static int
Neil Robertsb7f85332014-03-07 18:05:49 +00001904gl_renderer_setup_egl_extensions(struct weston_compositor *ec)
1905{
1906 struct gl_renderer *gr = get_renderer(ec);
1907 const char *extensions;
1908 EGLBoolean ret;
1909
1910 gr->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
1911 gr->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
1912 gr->bind_display =
1913 (void *) eglGetProcAddress("eglBindWaylandDisplayWL");
1914 gr->unbind_display =
1915 (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
1916 gr->query_buffer =
1917 (void *) eglGetProcAddress("eglQueryWaylandBufferWL");
1918
1919 extensions =
1920 (const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
1921 if (!extensions) {
1922 weston_log("Retrieving EGL extension string failed.\n");
1923 return -1;
1924 }
1925
1926 if (strstr(extensions, "EGL_WL_bind_wayland_display"))
1927 gr->has_bind_display = 1;
1928 if (gr->has_bind_display) {
1929 ret = gr->bind_display(gr->egl_display, ec->wl_display);
1930 if (!ret)
1931 gr->has_bind_display = 0;
1932 }
1933
1934 if (strstr(extensions, "EGL_EXT_buffer_age"))
1935 gr->has_egl_buffer_age = 1;
1936 else
1937 weston_log("warning: EGL_EXT_buffer_age not supported. "
1938 "Performance could be affected.\n");
1939
1940#ifdef EGL_EXT_swap_buffers_with_damage
1941 if (strstr(extensions, "EGL_EXT_swap_buffers_with_damage"))
1942 gr->swap_buffers_with_damage =
1943 (void *) eglGetProcAddress("eglSwapBuffersWithDamageEXT");
1944 else
1945 weston_log("warning: EGL_EXT_swap_buffers_with_damage not "
1946 "supported. Performance could be affected.\n");
1947#endif
1948
Neil Roberts77c1a5b2014-03-07 18:05:50 +00001949#ifdef EGL_MESA_configless_context
1950 if (strstr(extensions, "EGL_MESA_configless_context"))
1951 gr->has_configless_context = 1;
1952#endif
1953
Neil Robertsb7f85332014-03-07 18:05:49 +00001954 return 0;
1955}
1956
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001957static const EGLint gl_renderer_opaque_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001958 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1959 EGL_RED_SIZE, 1,
1960 EGL_GREEN_SIZE, 1,
1961 EGL_BLUE_SIZE, 1,
1962 EGL_ALPHA_SIZE, 0,
1963 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1964 EGL_NONE
1965};
1966
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001967static const EGLint gl_renderer_alpha_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001968 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1969 EGL_RED_SIZE, 1,
1970 EGL_GREEN_SIZE, 1,
1971 EGL_BLUE_SIZE, 1,
1972 EGL_ALPHA_SIZE, 1,
1973 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1974 EGL_NONE
1975};
1976
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001977static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001978gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001979 const EGLint *attribs, const EGLint *visual_id)
1980{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001981 struct gl_renderer *gr;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001982 EGLint major, minor;
1983
1984 gr = calloc(1, sizeof *gr);
1985
1986 if (gr == NULL)
1987 return -1;
1988
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001989 gr->base.read_pixels = gl_renderer_read_pixels;
1990 gr->base.repaint_output = gl_renderer_repaint_output;
1991 gr->base.flush_damage = gl_renderer_flush_damage;
1992 gr->base.attach = gl_renderer_attach;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001993 gr->base.surface_set_color = gl_renderer_surface_set_color;
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03001994 gr->base.destroy = gl_renderer_destroy;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001995
1996 gr->egl_display = eglGetDisplay(display);
1997 if (gr->egl_display == EGL_NO_DISPLAY) {
1998 weston_log("failed to create display\n");
1999 goto err_egl;
2000 }
2001
2002 if (!eglInitialize(gr->egl_display, &major, &minor)) {
2003 weston_log("failed to initialize display\n");
2004 goto err_egl;
2005 }
2006
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002007 if (egl_choose_config(gr, attribs, visual_id, &gr->egl_config) < 0) {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002008 weston_log("failed to choose EGL config\n");
2009 goto err_egl;
2010 }
2011
2012 ec->renderer = &gr->base;
Pekka Paalanen7bb65102013-05-22 18:03:04 +03002013 ec->capabilities |= WESTON_CAP_ROTATION_ANY;
Pekka Paalanen4fc5dd02013-05-22 18:03:05 +03002014 ec->capabilities |= WESTON_CAP_CAPTURE_YFLIP;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002015
Neil Robertsb7f85332014-03-07 18:05:49 +00002016 if (gl_renderer_setup_egl_extensions(ec) < 0)
2017 goto err_egl;
2018
Tomeu Vizoso12072b62013-08-06 20:05:55 +02002019 wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565);
2020
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03002021 wl_signal_init(&gr->destroy_signal);
2022
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002023 return 0;
2024
2025err_egl:
Pekka Paalanen326529f2012-11-27 12:25:25 +02002026 gl_renderer_print_egl_error_state();
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002027 free(gr);
2028 return -1;
2029}
2030
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002031static EGLDisplay
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002032gl_renderer_display(struct weston_compositor *ec)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002033{
2034 return get_renderer(ec)->egl_display;
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04002035}
2036
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002037static int
2038compile_shaders(struct weston_compositor *ec)
2039{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002040 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker40684142012-11-13 19:10:25 +01002041
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03002042 gr->texture_shader_rgba.vertex_source = vertex_shader;
2043 gr->texture_shader_rgba.fragment_source = texture_fragment_shader_rgba;
2044
2045 gr->texture_shader_rgbx.vertex_source = vertex_shader;
2046 gr->texture_shader_rgbx.fragment_source = texture_fragment_shader_rgbx;
2047
2048 gr->texture_shader_egl_external.vertex_source = vertex_shader;
2049 gr->texture_shader_egl_external.fragment_source =
2050 texture_fragment_shader_egl_external;
2051
2052 gr->texture_shader_y_uv.vertex_source = vertex_shader;
2053 gr->texture_shader_y_uv.fragment_source = texture_fragment_shader_y_uv;
2054
2055 gr->texture_shader_y_u_v.vertex_source = vertex_shader;
2056 gr->texture_shader_y_u_v.fragment_source =
2057 texture_fragment_shader_y_u_v;
2058
Ander Conselvan de Oliveira41a50ea2013-11-27 17:43:51 +02002059 gr->texture_shader_y_xuxv.vertex_source = vertex_shader;
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03002060 gr->texture_shader_y_xuxv.fragment_source =
2061 texture_fragment_shader_y_xuxv;
2062
2063 gr->solid_shader.vertex_source = vertex_shader;
2064 gr->solid_shader.fragment_source = solid_fragment_shader;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002065
2066 return 0;
2067}
2068
2069static void
Kristian Høgsberge3148752013-05-06 23:19:49 -04002070fragment_debug_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002071 void *data)
2072{
2073 struct weston_compositor *ec = data;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002074 struct gl_renderer *gr = get_renderer(ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002075 struct weston_output *output;
2076
John Kåre Alsaker40684142012-11-13 19:10:25 +01002077 gr->fragment_shader_debug ^= 1;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002078
John Kåre Alsaker40684142012-11-13 19:10:25 +01002079 shader_release(&gr->texture_shader_rgba);
2080 shader_release(&gr->texture_shader_rgbx);
2081 shader_release(&gr->texture_shader_egl_external);
2082 shader_release(&gr->texture_shader_y_uv);
2083 shader_release(&gr->texture_shader_y_u_v);
2084 shader_release(&gr->texture_shader_y_xuxv);
2085 shader_release(&gr->solid_shader);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002086
Ander Conselvan de Oliveira03fb4ef2012-12-03 17:08:11 +02002087 /* Force use_shader() to call glUseProgram(), since we need to use
2088 * the recompiled version of the shader. */
2089 gr->current_shader = NULL;
2090
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002091 wl_list_for_each(output, &ec->output_list, link)
2092 weston_output_damage(output);
2093}
2094
Kristian Høgsberg8799d412013-05-07 10:50:09 -04002095static void
2096fan_debug_repaint_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
2097 void *data)
2098{
2099 struct weston_compositor *compositor = data;
2100 struct gl_renderer *gr = get_renderer(compositor);
2101
2102 gr->fan_debug = !gr->fan_debug;
2103 weston_compositor_damage_all(compositor);
2104}
2105
John Kåre Alsaker94659272012-11-13 19:10:18 +01002106static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002107gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002108{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002109 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002110 const char *extensions;
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002111 EGLConfig context_config;
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04002112 EGLBoolean ret;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002113
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04002114 static const EGLint context_attribs[] = {
2115 EGL_CONTEXT_CLIENT_VERSION, 2,
2116 EGL_NONE
2117 };
2118
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04002119 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
2120 weston_log("failed to bind EGL_OPENGL_ES_API\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02002121 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04002122 return -1;
2123 }
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03002124
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002125 context_config = gr->egl_config;
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03002126
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002127#ifdef EGL_MESA_configless_context
2128 if (gr->has_configless_context)
2129 context_config = EGL_NO_CONFIG_MESA;
2130#endif
2131
2132 gr->egl_context = eglCreateContext(gr->egl_display, context_config,
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04002133 EGL_NO_CONTEXT, context_attribs);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002134 if (gr->egl_context == NULL) {
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04002135 weston_log("failed to create context\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02002136 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04002137 return -1;
2138 }
2139
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002140 ret = eglMakeCurrent(gr->egl_display, egl_surface,
2141 egl_surface, gr->egl_context);
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04002142 if (ret == EGL_FALSE) {
2143 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02002144 gl_renderer_print_egl_error_state();
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04002145 return -1;
2146 }
2147
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002148 log_egl_gl_info(gr->egl_display);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002149
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002150 gr->image_target_texture_2d =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002151 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002152
2153 extensions = (const char *) glGetString(GL_EXTENSIONS);
2154 if (!extensions) {
2155 weston_log("Retrieving GL extension string failed.\n");
2156 return -1;
2157 }
2158
2159 if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
2160 weston_log("GL_EXT_texture_format_BGRA8888 not available\n");
2161 return -1;
2162 }
2163
2164 if (strstr(extensions, "GL_EXT_read_format_bgra"))
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01002165 ec->read_format = PIXMAN_a8r8g8b8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002166 else
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01002167 ec->read_format = PIXMAN_a8b8g8r8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002168
Kristian Høgsberg1c4f1632013-08-07 12:11:27 -07002169#ifdef GL_EXT_unpack_subimage
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002170 if (strstr(extensions, "GL_EXT_unpack_subimage"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002171 gr->has_unpack_subimage = 1;
Kristian Høgsberg1c4f1632013-08-07 12:11:27 -07002172#endif
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002173
2174 if (strstr(extensions, "GL_OES_EGL_image_external"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002175 gr->has_egl_image_external = 1;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002176
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002177 glActiveTexture(GL_TEXTURE0);
2178
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002179 if (compile_shaders(ec))
2180 return -1;
2181
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +03002182 gr->fragment_binding =
2183 weston_compositor_add_debug_binding(ec, KEY_S,
2184 fragment_debug_binding,
2185 ec);
2186 gr->fan_binding =
2187 weston_compositor_add_debug_binding(ec, KEY_F,
2188 fan_debug_repaint_binding,
2189 ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002190
Pekka Paalanen035a0322012-10-24 09:43:06 +03002191 weston_log("GL ES 2 renderer features:\n");
2192 weston_log_continue(STAMP_SPACE "read-back format: %s\n",
Pekka Paalanenfe4eacf2013-01-10 16:50:42 +02002193 ec->read_format == PIXMAN_a8r8g8b8 ? "BGRA" : "RGBA");
Pekka Paalanen035a0322012-10-24 09:43:06 +03002194 weston_log_continue(STAMP_SPACE "wl_shm sub-image to texture: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002195 gr->has_unpack_subimage ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03002196 weston_log_continue(STAMP_SPACE "EGL Wayland extension: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002197 gr->has_bind_display ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03002198
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002199
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002200 return 0;
2201}
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002202
2203WL_EXPORT struct gl_renderer_interface gl_renderer_interface = {
2204 .opaque_attribs = gl_renderer_opaque_attribs,
2205 .alpha_attribs = gl_renderer_alpha_attribs,
2206
2207 .create = gl_renderer_create,
2208 .display = gl_renderer_display,
2209 .output_create = gl_renderer_output_create,
2210 .output_destroy = gl_renderer_output_destroy,
2211 .output_surface = gl_renderer_output_surface,
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05002212 .output_set_border = gl_renderer_output_set_border,
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002213 .print_egl_error_state = gl_renderer_print_egl_error_state
2214};