blob: 2cb24fac338e75ed69aa71676dac9e0bf89bfef1 [file] [log] [blame]
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001/*
2 * Copyright © 2012 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
Daniel Stonec228e232013-05-22 18:03:19 +030023#include "config.h"
Kristian Høgsberg25894fc2012-09-05 22:06:26 -040024
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010025#include <GLES2/gl2.h>
26#include <GLES2/gl2ext.h>
27
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -040028#include <stdlib.h>
Kristian Høgsberg25894fc2012-09-05 22:06:26 -040029#include <string.h>
30#include <ctype.h>
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +030031#include <float.h>
32#include <assert.h>
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +020033#include <linux/input.h>
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -040034
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010035#include "gl-renderer.h"
Sam Spilsbury619859c2013-09-13 10:01:21 +080036#include "vertex-clipping.h"
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010037
38#include <EGL/eglext.h>
39#include "weston-egl-ext.h"
Kristian Høgsbergd7c17262012-09-05 21:54:15 -040040
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010041struct gl_shader {
John Kåre Alsaker40684142012-11-13 19:10:25 +010042 GLuint program;
43 GLuint vertex_shader, fragment_shader;
44 GLint proj_uniform;
45 GLint tex_uniforms[3];
46 GLint alpha_uniform;
47 GLint color_uniform;
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +030048 const char *vertex_source, *fragment_source;
John Kåre Alsaker40684142012-11-13 19:10:25 +010049};
50
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +020051#define BUFFER_DAMAGE_COUNT 2
52
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010053struct gl_output_state {
John Kåre Alsaker94659272012-11-13 19:10:18 +010054 EGLSurface egl_surface;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +020055 pixman_region32_t buffer_damage[BUFFER_DAMAGE_COUNT];
John Kåre Alsaker94659272012-11-13 19:10:18 +010056};
57
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +030058enum buffer_type {
59 BUFFER_TYPE_NULL,
60 BUFFER_TYPE_SHM,
61 BUFFER_TYPE_EGL
62};
63
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010064struct gl_surface_state {
John Kåre Alsaker878f4492012-11-13 19:10:23 +010065 GLfloat color[4];
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010066 struct gl_shader *shader;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +010067
68 GLuint textures[3];
69 int num_textures;
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +030070 int needs_full_upload;
Pekka Paalanen81ee3f52012-12-04 15:58:16 +020071 pixman_region32_t texture_damage;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +010072
73 EGLImageKHR images[3];
74 GLenum target;
75 int num_images;
Pekka Paalanenfb003d32012-12-04 15:58:13 +020076
77 struct weston_buffer_reference buffer_ref;
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +030078 enum buffer_type buffer_type;
Pekka Paalanen68033ac2012-12-04 15:58:15 +020079 int pitch; /* in pixels */
Alexander Larsson4ea95522013-05-22 14:41:37 +020080 int height; /* in pixels */
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +040081 int y_inverted;
John Kåre Alsaker878f4492012-11-13 19:10:23 +010082};
83
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010084struct gl_renderer {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +010085 struct weston_renderer base;
86 int fragment_shader_debug;
Kristian Høgsberg8799d412013-05-07 10:50:09 -040087 int fan_debug;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +010088
89 EGLDisplay egl_display;
90 EGLContext egl_context;
91 EGLConfig egl_config;
John Kåre Alsaker44154502012-11-13 19:10:20 +010092
93 struct {
94 int32_t top, bottom, left, right;
95 GLuint texture;
96 int32_t width, height;
97 } border;
John Kåre Alsaker40684142012-11-13 19:10:25 +010098
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -040099 struct wl_array vertices;
100 struct wl_array indices; /* only used in compositor-wayland */
101 struct wl_array vtxcnt;
102
John Kåre Alsaker320711d2012-11-13 19:10:27 +0100103 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
104 PFNEGLCREATEIMAGEKHRPROC create_image;
105 PFNEGLDESTROYIMAGEKHRPROC destroy_image;
106
107 int has_unpack_subimage;
108
109 PFNEGLBINDWAYLANDDISPLAYWL bind_display;
110 PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
111 PFNEGLQUERYWAYLANDBUFFERWL query_buffer;
112 int has_bind_display;
113
114 int has_egl_image_external;
115
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200116 int has_egl_buffer_age;
117
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100118 struct gl_shader texture_shader_rgba;
119 struct gl_shader texture_shader_rgbx;
120 struct gl_shader texture_shader_egl_external;
121 struct gl_shader texture_shader_y_uv;
122 struct gl_shader texture_shader_y_u_v;
123 struct gl_shader texture_shader_y_xuxv;
124 struct gl_shader invert_color_shader;
125 struct gl_shader solid_shader;
126 struct gl_shader *current_shader;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100127};
John Kåre Alsaker94659272012-11-13 19:10:18 +0100128
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100129static inline struct gl_output_state *
John Kåre Alsaker94659272012-11-13 19:10:18 +0100130get_output_state(struct weston_output *output)
131{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100132 return (struct gl_output_state *)output->renderer_state;
John Kåre Alsaker94659272012-11-13 19:10:18 +0100133}
134
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100135static inline struct gl_surface_state *
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100136get_surface_state(struct weston_surface *surface)
137{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100138 return (struct gl_surface_state *)surface->renderer_state;
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100139}
140
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100141static inline struct gl_renderer *
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100142get_renderer(struct weston_compositor *ec)
143{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100144 return (struct gl_renderer *)ec->renderer;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100145}
146
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400147static const char *
148egl_error_string(EGLint code)
149{
150#define MYERRCODE(x) case x: return #x;
151 switch (code) {
152 MYERRCODE(EGL_SUCCESS)
153 MYERRCODE(EGL_NOT_INITIALIZED)
154 MYERRCODE(EGL_BAD_ACCESS)
155 MYERRCODE(EGL_BAD_ALLOC)
156 MYERRCODE(EGL_BAD_ATTRIBUTE)
157 MYERRCODE(EGL_BAD_CONTEXT)
158 MYERRCODE(EGL_BAD_CONFIG)
159 MYERRCODE(EGL_BAD_CURRENT_SURFACE)
160 MYERRCODE(EGL_BAD_DISPLAY)
161 MYERRCODE(EGL_BAD_SURFACE)
162 MYERRCODE(EGL_BAD_MATCH)
163 MYERRCODE(EGL_BAD_PARAMETER)
164 MYERRCODE(EGL_BAD_NATIVE_PIXMAP)
165 MYERRCODE(EGL_BAD_NATIVE_WINDOW)
166 MYERRCODE(EGL_CONTEXT_LOST)
167 default:
168 return "unknown";
169 }
170#undef MYERRCODE
171}
172
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +0300173static void
Pekka Paalanen326529f2012-11-27 12:25:25 +0200174gl_renderer_print_egl_error_state(void)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400175{
176 EGLint code;
177
178 code = eglGetError();
179 weston_log("EGL error state: %s (0x%04lx)\n",
180 egl_error_string(code), (long)code);
181}
182
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400183#define max(a, b) (((a) > (b)) ? (a) : (b))
184#define min(a, b) (((a) > (b)) ? (b) : (a))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400185
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300186/*
187 * Compute the boundary vertices of the intersection of the global coordinate
188 * aligned rectangle 'rect', and an arbitrary quadrilateral produced from
189 * 'surf_rect' when transformed from surface coordinates into global coordinates.
190 * The vertices are written to 'ex' and 'ey', and the return value is the
191 * number of vertices. Vertices are produced in clockwise winding order.
192 * Guarantees to produce either zero vertices, or 3-8 vertices with non-zero
193 * polygon area.
194 */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400195static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500196calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400197 pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
198{
Sam Spilsbury619859c2013-09-13 10:01:21 +0800199
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300200 struct clip_context ctx;
201 int i, n;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400202 GLfloat min_x, max_x, min_y, max_y;
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300203 struct polygon8 surf = {
204 { surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1 },
205 { surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2 },
206 4
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400207 };
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400208
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300209 ctx.clip.x1 = rect->x1;
210 ctx.clip.y1 = rect->y1;
211 ctx.clip.x2 = rect->x2;
212 ctx.clip.y2 = rect->y2;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400213
214 /* transform surface to screen space: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300215 for (i = 0; i < surf.n; i++)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500216 weston_view_to_global_float(ev, surf.x[i], surf.y[i],
217 &surf.x[i], &surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400218
219 /* find bounding box: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300220 min_x = max_x = surf.x[0];
221 min_y = max_y = surf.y[0];
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400222
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300223 for (i = 1; i < surf.n; i++) {
224 min_x = min(min_x, surf.x[i]);
225 max_x = max(max_x, surf.x[i]);
226 min_y = min(min_y, surf.y[i]);
227 max_y = max(max_y, surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400228 }
229
230 /* First, simple bounding box check to discard early transformed
231 * surface rects that do not intersect with the clip region:
232 */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300233 if ((min_x >= ctx.clip.x2) || (max_x <= ctx.clip.x1) ||
234 (min_y >= ctx.clip.y2) || (max_y <= ctx.clip.y1))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400235 return 0;
236
237 /* Simple case, bounding box edges are parallel to surface edges,
238 * there will be only four edges. We just need to clip the surface
239 * vertices to the clip rect bounds:
240 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500241 if (!ev->transform.enabled)
Sam Spilsbury619859c2013-09-13 10:01:21 +0800242 return clip_simple(&ctx, &surf, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400243
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300244 /* Transformed case: use a general polygon clipping algorithm to
245 * clip the surface rectangle with each side of 'rect'.
246 * The algorithm is Sutherland-Hodgman, as explained in
247 * http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm
248 * but without looking at any of that code.
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400249 */
Sam Spilsbury619859c2013-09-13 10:01:21 +0800250 n = clip_transformed(&ctx, &surf, ex, ey);
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300251
252 if (n < 3)
253 return 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400254
255 return n;
256}
257
258static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500259texture_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400260 pixman_region32_t *surf_region)
261{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500262 struct gl_surface_state *gs = get_surface_state(ev->surface);
263 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400264 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400265 GLfloat *v, inv_width, inv_height;
266 unsigned int *vtxcnt, nvtx = 0;
267 pixman_box32_t *rects, *surf_rects;
268 int i, j, k, nrects, nsurf;
269
270 rects = pixman_region32_rectangles(region, &nrects);
271 surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
272
273 /* worst case we can have 8 vertices per rect (ie. clipped into
274 * an octagon):
275 */
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400276 v = wl_array_add(&gr->vertices, nrects * nsurf * 8 * 4 * sizeof *v);
277 vtxcnt = wl_array_add(&gr->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400278
Pekka Paalanen68033ac2012-12-04 15:58:15 +0200279 inv_width = 1.0 / gs->pitch;
Alexander Larsson4ea95522013-05-22 14:41:37 +0200280 inv_height = 1.0 / gs->height;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400281
282 for (i = 0; i < nrects; i++) {
283 pixman_box32_t *rect = &rects[i];
284 for (j = 0; j < nsurf; j++) {
285 pixman_box32_t *surf_rect = &surf_rects[j];
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200286 GLfloat sx, sy, bx, by;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400287 GLfloat ex[8], ey[8]; /* edge points in screen space */
288 int n;
289
290 /* The transformed surface, after clipping to the clip region,
291 * can have as many as eight sides, emitted as a triangle-fan.
292 * The first vertex in the triangle fan can be chosen arbitrarily,
293 * since the area is guaranteed to be convex.
294 *
295 * If a corner of the transformed surface falls outside of the
296 * clip region, instead of emitting one vertex for the corner
297 * of the surface, up to two are emitted for two corresponding
298 * intersection point(s) between the surface and the clip region.
299 *
300 * To do this, we first calculate the (up to eight) points that
301 * form the intersection of the clip rect and the transformed
302 * surface.
303 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500304 n = calculate_edges(ev, rect, surf_rect, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400305 if (n < 3)
306 continue;
307
308 /* emit edge points: */
309 for (k = 0; k < n; k++) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500310 weston_view_from_global_float(ev, ex[k], ey[k],
311 &sx, &sy);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400312 /* position: */
313 *(v++) = ex[k];
314 *(v++) = ey[k];
315 /* texcoord: */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500316 weston_surface_to_buffer_float(ev->surface,
317 sx, sy,
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200318 &bx, &by);
319 *(v++) = bx * inv_width;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +0400320 if (gs->y_inverted) {
321 *(v++) = by * inv_height;
322 } else {
323 *(v++) = (gs->height - by) * inv_height;
324 }
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400325 }
326
327 vtxcnt[nvtx++] = n;
328 }
329 }
330
331 return nvtx;
332}
333
334static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500335triangle_fan_debug(struct weston_view *view, int first, int count)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400336{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500337 struct weston_compositor *compositor = view->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100338 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400339 int i;
340 GLushort *buffer;
341 GLushort *index;
342 int nelems;
343 static int color_idx = 0;
344 static const GLfloat color[][4] = {
345 { 1.0, 0.0, 0.0, 1.0 },
346 { 0.0, 1.0, 0.0, 1.0 },
347 { 0.0, 0.0, 1.0, 1.0 },
348 { 1.0, 1.0, 1.0, 1.0 },
349 };
350
351 nelems = (count - 1 + count - 2) * 2;
352
353 buffer = malloc(sizeof(GLushort) * nelems);
354 index = buffer;
355
356 for (i = 1; i < count; i++) {
357 *index++ = first;
358 *index++ = first + i;
359 }
360
361 for (i = 2; i < count; i++) {
362 *index++ = first + i - 1;
363 *index++ = first + i;
364 }
365
John Kåre Alsaker40684142012-11-13 19:10:25 +0100366 glUseProgram(gr->solid_shader.program);
367 glUniform4fv(gr->solid_shader.color_uniform, 1,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400368 color[color_idx++ % ARRAY_LENGTH(color)]);
369 glDrawElements(GL_LINES, nelems, GL_UNSIGNED_SHORT, buffer);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100370 glUseProgram(gr->current_shader->program);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400371 free(buffer);
372}
373
374static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500375repaint_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400376 pixman_region32_t *surf_region)
377{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500378 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400379 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400380 GLfloat *v;
381 unsigned int *vtxcnt;
382 int i, first, nfans;
383
384 /* The final region to be painted is the intersection of
385 * 'region' and 'surf_region'. However, 'region' is in the global
386 * coordinates, and 'surf_region' is in the surface-local
387 * coordinates. texture_region() will iterate over all pairs of
388 * rectangles from both regions, compute the intersection
389 * polygon for each pair, and store it as a triangle fan if
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400390 * it has a non-zero area (at least 3 vertices1, actually).
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400391 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500392 nfans = texture_region(ev, region, surf_region);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400393
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400394 v = gr->vertices.data;
395 vtxcnt = gr->vtxcnt.data;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400396
397 /* position: */
398 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
399 glEnableVertexAttribArray(0);
400
401 /* texcoord: */
402 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
403 glEnableVertexAttribArray(1);
404
405 for (i = 0, first = 0; i < nfans; i++) {
406 glDrawArrays(GL_TRIANGLE_FAN, first, vtxcnt[i]);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400407 if (gr->fan_debug)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500408 triangle_fan_debug(ev, first, vtxcnt[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400409 first += vtxcnt[i];
410 }
411
412 glDisableVertexAttribArray(1);
413 glDisableVertexAttribArray(0);
414
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400415 gr->vertices.size = 0;
416 gr->vtxcnt.size = 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400417}
418
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100419static int
420use_output(struct weston_output *output)
421{
422 static int errored;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100423 struct gl_output_state *go = get_output_state(output);
424 struct gl_renderer *gr = get_renderer(output->compositor);
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100425 EGLBoolean ret;
426
427 ret = eglMakeCurrent(gr->egl_display, go->egl_surface,
428 go->egl_surface, gr->egl_context);
429
430 if (ret == EGL_FALSE) {
431 if (errored)
432 return -1;
433 errored = 1;
434 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +0200435 gl_renderer_print_egl_error_state();
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100436 return -1;
437 }
438
439 return 0;
440}
441
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300442static int
443shader_init(struct gl_shader *shader, struct gl_renderer *gr,
444 const char *vertex_source, const char *fragment_source);
445
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400446static void
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300447use_shader(struct gl_renderer *gr, struct gl_shader *shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400448{
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300449 if (!shader->program) {
450 int ret;
451
452 ret = shader_init(shader, gr,
453 shader->vertex_source,
454 shader->fragment_source);
455
456 if (ret < 0)
457 weston_log("warning: failed to compile shader\n");
458 }
459
John Kåre Alsaker40684142012-11-13 19:10:25 +0100460 if (gr->current_shader == shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400461 return;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400462 glUseProgram(shader->program);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100463 gr->current_shader = shader;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400464}
465
466static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100467shader_uniforms(struct gl_shader *shader,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500468 struct weston_view *view,
469 struct weston_output *output)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400470{
471 int i;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500472 struct gl_surface_state *gs = get_surface_state(view->surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400473
474 glUniformMatrix4fv(shader->proj_uniform,
475 1, GL_FALSE, output->matrix.d);
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100476 glUniform4fv(shader->color_uniform, 1, gs->color);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500477 glUniform1f(shader->alpha_uniform, view->alpha);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400478
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100479 for (i = 0; i < gs->num_textures; i++)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400480 glUniform1i(shader->tex_uniforms[i], i);
481}
482
483static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500484draw_view(struct weston_view *ev, struct weston_output *output,
485 pixman_region32_t *damage) /* in global coordinates */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400486{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500487 struct weston_compositor *ec = ev->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100488 struct gl_renderer *gr = get_renderer(ec);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500489 struct gl_surface_state *gs = get_surface_state(ev->surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400490 /* repaint bounding region in global coordinates: */
491 pixman_region32_t repaint;
492 /* non-opaque region in surface coordinates: */
493 pixman_region32_t surface_blend;
494 GLint filter;
495 int i;
496
497 pixman_region32_init(&repaint);
498 pixman_region32_intersect(&repaint,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500499 &ev->transform.boundingbox, damage);
500 pixman_region32_subtract(&repaint, &repaint, &ev->clip);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400501
502 if (!pixman_region32_not_empty(&repaint))
503 goto out;
504
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400505 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
506
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400507 if (gr->fan_debug) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100508 use_shader(gr, &gr->solid_shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500509 shader_uniforms(&gr->solid_shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400510 }
511
John Kåre Alsaker40684142012-11-13 19:10:25 +0100512 use_shader(gr, gs->shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500513 shader_uniforms(gs->shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400514
Jason Ekstranda7af7042013-10-12 22:38:11 -0500515 if (ev->transform.enabled || output->zoom.active ||
516 output->current_scale != ev->surface->buffer_scale)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400517 filter = GL_LINEAR;
518 else
519 filter = GL_NEAREST;
520
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100521 for (i = 0; i < gs->num_textures; i++) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400522 glActiveTexture(GL_TEXTURE0 + i);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100523 glBindTexture(gs->target, gs->textures[i]);
524 glTexParameteri(gs->target, GL_TEXTURE_MIN_FILTER, filter);
525 glTexParameteri(gs->target, GL_TEXTURE_MAG_FILTER, filter);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400526 }
527
528 /* blended region is whole surface minus opaque region: */
529 pixman_region32_init_rect(&surface_blend, 0, 0,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500530 ev->geometry.width, ev->geometry.height);
531 pixman_region32_subtract(&surface_blend, &surface_blend, &ev->surface->opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400532
Jason Ekstranda7af7042013-10-12 22:38:11 -0500533 /* XXX: Should we be using ev->transform.opaque here? */
534 if (pixman_region32_not_empty(&ev->surface->opaque)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100535 if (gs->shader == &gr->texture_shader_rgba) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400536 /* Special case for RGBA textures with possibly
537 * bad data in alpha channel: use the shader
538 * that forces texture alpha = 1.0.
539 * Xwayland surfaces need this.
540 */
John Kåre Alsaker40684142012-11-13 19:10:25 +0100541 use_shader(gr, &gr->texture_shader_rgbx);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500542 shader_uniforms(&gr->texture_shader_rgbx, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400543 }
544
Jason Ekstranda7af7042013-10-12 22:38:11 -0500545 if (ev->alpha < 1.0)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400546 glEnable(GL_BLEND);
547 else
548 glDisable(GL_BLEND);
549
Jason Ekstranda7af7042013-10-12 22:38:11 -0500550 repaint_region(ev, &repaint, &ev->surface->opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400551 }
552
553 if (pixman_region32_not_empty(&surface_blend)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100554 use_shader(gr, gs->shader);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400555 glEnable(GL_BLEND);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500556 repaint_region(ev, &repaint, &surface_blend);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400557 }
558
559 pixman_region32_fini(&surface_blend);
560
561out:
562 pixman_region32_fini(&repaint);
563}
564
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400565static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500566repaint_views(struct weston_output *output, pixman_region32_t *damage)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400567{
568 struct weston_compositor *compositor = output->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500569 struct weston_view *view;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400570
Jason Ekstranda7af7042013-10-12 22:38:11 -0500571 wl_list_for_each_reverse(view, &compositor->view_list, link)
572 if (view->plane == &compositor->primary_plane)
573 draw_view(view, output, damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400574}
575
John Kåre Alsaker44154502012-11-13 19:10:20 +0100576
577static int
578texture_border(struct weston_output *output)
579{
580 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100581 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100582 GLfloat *d;
Kristian Høgsberg73db9242013-08-28 23:05:29 -0700583 unsigned short *p;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100584 int i, j, k, n;
585 GLfloat x[4], y[4], u[4], v[4];
586
587 x[0] = -gr->border.left;
588 x[1] = 0;
Hardeningff39efa2013-09-18 23:56:35 +0200589 x[2] = output->current_mode->width;
590 x[3] = output->current_mode->width + gr->border.right;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100591
592 y[0] = -gr->border.top;
593 y[1] = 0;
Hardeningff39efa2013-09-18 23:56:35 +0200594 y[2] = output->current_mode->height;
595 y[3] = output->current_mode->height + gr->border.bottom;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100596
597 u[0] = 0.0;
598 u[1] = (GLfloat) gr->border.left / gr->border.width;
599 u[2] = (GLfloat) (gr->border.width - gr->border.right) / gr->border.width;
600 u[3] = 1.0;
601
602 v[0] = 0.0;
603 v[1] = (GLfloat) gr->border.top / gr->border.height;
604 v[2] = (GLfloat) (gr->border.height - gr->border.bottom) / gr->border.height;
605 v[3] = 1.0;
606
607 n = 8;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400608 d = wl_array_add(&gr->vertices, n * 16 * sizeof *d);
609 p = wl_array_add(&gr->indices, n * 6 * sizeof *p);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100610
611 k = 0;
612 for (i = 0; i < 3; i++)
613 for (j = 0; j < 3; j++) {
614
615 if (i == 1 && j == 1)
616 continue;
617
618 d[ 0] = x[i];
619 d[ 1] = y[j];
620 d[ 2] = u[i];
621 d[ 3] = v[j];
622
623 d[ 4] = x[i];
624 d[ 5] = y[j + 1];
625 d[ 6] = u[i];
626 d[ 7] = v[j + 1];
627
628 d[ 8] = x[i + 1];
629 d[ 9] = y[j];
630 d[10] = u[i + 1];
631 d[11] = v[j];
632
633 d[12] = x[i + 1];
634 d[13] = y[j + 1];
635 d[14] = u[i + 1];
636 d[15] = v[j + 1];
637
638 p[0] = k + 0;
639 p[1] = k + 1;
640 p[2] = k + 2;
641 p[3] = k + 2;
642 p[4] = k + 1;
643 p[5] = k + 3;
644
645 d += 16;
646 p += 6;
647 k += 4;
648 }
649
650 return k / 4;
651}
652
653static void
654draw_border(struct weston_output *output)
655{
656 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100657 struct gl_renderer *gr = get_renderer(ec);
658 struct gl_shader *shader = &gr->texture_shader_rgba;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100659 GLfloat *v;
660 int n;
661
662 glDisable(GL_BLEND);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100663 use_shader(gr, shader);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100664
665 glUniformMatrix4fv(shader->proj_uniform,
666 1, GL_FALSE, output->matrix.d);
667
668 glUniform1i(shader->tex_uniforms[0], 0);
669 glUniform1f(shader->alpha_uniform, 1);
670
671 n = texture_border(output);
672
673 glActiveTexture(GL_TEXTURE0);
674 glBindTexture(GL_TEXTURE_2D, gr->border.texture);
675
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400676 v = gr->vertices.data;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100677 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
678 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
679 glEnableVertexAttribArray(0);
680 glEnableVertexAttribArray(1);
681
682 glDrawElements(GL_TRIANGLES, n * 6,
Kristian Høgsberg73db9242013-08-28 23:05:29 -0700683 GL_UNSIGNED_SHORT, gr->indices.data);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100684
685 glDisableVertexAttribArray(1);
686 glDisableVertexAttribArray(0);
687
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400688 gr->vertices.size = 0;
689 gr->indices.size = 0;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100690}
691
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400692static void
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200693output_get_buffer_damage(struct weston_output *output,
694 pixman_region32_t *buffer_damage)
695{
696 struct gl_output_state *go = get_output_state(output);
697 struct gl_renderer *gr = get_renderer(output->compositor);
698 EGLint buffer_age = 0;
699 EGLBoolean ret;
700 int i;
701
702 if (gr->has_egl_buffer_age) {
703 ret = eglQuerySurface(gr->egl_display, go->egl_surface,
704 EGL_BUFFER_AGE_EXT, &buffer_age);
705 if (ret == EGL_FALSE) {
706 weston_log("buffer age query failed.\n");
707 gl_renderer_print_egl_error_state();
708 }
709 }
710
711 if (buffer_age == 0 || buffer_age - 1 > BUFFER_DAMAGE_COUNT)
712 pixman_region32_copy(buffer_damage, &output->region);
713 else
714 for (i = 0; i < buffer_age - 1; i++)
715 pixman_region32_union(buffer_damage, buffer_damage,
716 &go->buffer_damage[i]);
717}
718
719static void
720output_rotate_damage(struct weston_output *output,
721 pixman_region32_t *output_damage)
722{
723 struct gl_output_state *go = get_output_state(output);
724 struct gl_renderer *gr = get_renderer(output->compositor);
725 int i;
726
727 if (!gr->has_egl_buffer_age)
728 return;
729
730 for (i = BUFFER_DAMAGE_COUNT - 1; i >= 1; i--)
731 pixman_region32_copy(&go->buffer_damage[i],
732 &go->buffer_damage[i - 1]);
733
734 pixman_region32_copy(&go->buffer_damage[0], output_damage);
735}
736
737static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100738gl_renderer_repaint_output(struct weston_output *output,
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400739 pixman_region32_t *output_damage)
740{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100741 struct gl_output_state *go = get_output_state(output);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400742 struct weston_compositor *compositor = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100743 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400744 EGLBoolean ret;
745 static int errored;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200746 int32_t width, height;
747 pixman_region32_t buffer_damage, total_damage;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400748
Hardeningff39efa2013-09-18 23:56:35 +0200749 width = output->current_mode->width +
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400750 output->border.left + output->border.right;
Hardeningff39efa2013-09-18 23:56:35 +0200751 height = output->current_mode->height +
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400752 output->border.top + output->border.bottom;
753
754 glViewport(0, 0, width, height);
755
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100756 if (use_output(output) < 0)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400757 return;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400758
759 /* if debugging, redraw everything outside the damage to clean up
760 * debug lines from the previous draw on this buffer:
761 */
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400762 if (gr->fan_debug) {
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400763 pixman_region32_t undamaged;
764 pixman_region32_init(&undamaged);
765 pixman_region32_subtract(&undamaged, &output->region,
766 output_damage);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400767 gr->fan_debug = 0;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500768 repaint_views(output, &undamaged);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400769 gr->fan_debug = 1;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400770 pixman_region32_fini(&undamaged);
771 }
772
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +0200773 pixman_region32_init(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200774 pixman_region32_init(&buffer_damage);
775
776 output_get_buffer_damage(output, &buffer_damage);
777 output_rotate_damage(output, output_damage);
778
779 pixman_region32_union(&total_damage, &buffer_damage, output_damage);
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300780
Jason Ekstranda7af7042013-10-12 22:38:11 -0500781 repaint_views(output, &total_damage);
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +0200782
783 pixman_region32_fini(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200784 pixman_region32_fini(&buffer_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400785
John Kåre Alsaker44154502012-11-13 19:10:20 +0100786 if (gr->border.texture)
787 draw_border(output);
788
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +0200789 pixman_region32_copy(&output->previous_damage, output_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400790 wl_signal_emit(&output->frame_signal, output);
791
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100792 ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400793 if (ret == EGL_FALSE && !errored) {
794 errored = 1;
795 weston_log("Failed in eglSwapBuffers.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +0200796 gl_renderer_print_egl_error_state();
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400797 }
798
799}
Kristian Høgsberg25894fc2012-09-05 22:06:26 -0400800
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100801static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100802gl_renderer_read_pixels(struct weston_output *output,
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100803 pixman_format_code_t format, void *pixels,
804 uint32_t x, uint32_t y,
805 uint32_t width, uint32_t height)
806{
807 GLenum gl_format;
808
809 switch (format) {
810 case PIXMAN_a8r8g8b8:
811 gl_format = GL_BGRA_EXT;
812 break;
813 case PIXMAN_a8b8g8r8:
814 gl_format = GL_RGBA;
815 break;
816 default:
817 return -1;
818 }
819
820 if (use_output(output) < 0)
821 return -1;
822
823 glPixelStorei(GL_PACK_ALIGNMENT, 1);
824 glReadPixels(x, y, width, height, gl_format,
825 GL_UNSIGNED_BYTE, pixels);
826
827 return 0;
828}
829
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400830static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100831gl_renderer_flush_damage(struct weston_surface *surface)
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400832{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100833 struct gl_renderer *gr = get_renderer(surface->compositor);
834 struct gl_surface_state *gs = get_surface_state(surface);
Jason Ekstrand6bd62942013-06-20 20:38:23 -0500835 struct weston_buffer *buffer = gs->buffer_ref.buffer;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500836 struct weston_view *view;
837 int texture_used;
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200838 GLenum format;
839 int pixel_type;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100840
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700841#ifdef GL_EXT_unpack_subimage
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400842 pixman_box32_t *rectangles;
843 void *data;
844 int i, n;
845#endif
846
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200847 pixman_region32_union(&gs->texture_damage,
848 &gs->texture_damage, &surface->damage);
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200849
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200850 if (!buffer)
851 return;
852
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200853 /* Avoid upload, if the texture won't be used this time.
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200854 * We still accumulate the damage in texture_damage, and
855 * hold the reference to the buffer, in case the surface
856 * migrates back to the primary plane.
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200857 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500858 texture_used = 0;
859 wl_list_for_each(view, &surface->views, surface_link) {
860 if (view->plane == &surface->compositor->primary_plane) {
861 texture_used = 1;
862 break;
863 }
864 }
865 if (!texture_used)
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200866 return;
867
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200868 if (!pixman_region32_not_empty(&gs->texture_damage))
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200869 goto done;
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200870
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200871 switch (wl_shm_buffer_get_format(buffer->shm_buffer)) {
872 case WL_SHM_FORMAT_XRGB8888:
873 case WL_SHM_FORMAT_ARGB8888:
874 format = GL_BGRA_EXT;
875 pixel_type = GL_UNSIGNED_BYTE;
876 break;
877 case WL_SHM_FORMAT_RGB565:
878 format = GL_RGB;
879 pixel_type = GL_UNSIGNED_SHORT_5_6_5;
880 break;
881 default:
882 weston_log("warning: unknown shm buffer format\n");
883 format = GL_BGRA_EXT;
884 pixel_type = GL_UNSIGNED_BYTE;
885 }
886
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100887 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400888
John Kåre Alsaker320711d2012-11-13 19:10:27 +0100889 if (!gr->has_unpack_subimage) {
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200890 glTexImage2D(GL_TEXTURE_2D, 0, format,
Pekka Paalanen68033ac2012-12-04 15:58:15 +0200891 gs->pitch, buffer->height, 0,
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200892 format, pixel_type,
Jason Ekstrand6bd62942013-06-20 20:38:23 -0500893 wl_shm_buffer_get_data(buffer->shm_buffer));
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400894
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200895 goto done;
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400896 }
897
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700898#ifdef GL_EXT_unpack_subimage
899 glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, gs->pitch);
Jason Ekstrand6bd62942013-06-20 20:38:23 -0500900 data = wl_shm_buffer_get_data(buffer->shm_buffer);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300901
902 if (gs->needs_full_upload) {
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700903 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
904 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300905 glTexSubImage2D(GL_TEXTURE_2D, 0,
906 0, 0, gs->pitch, buffer->height,
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200907 format, pixel_type, data);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300908 goto done;
909 }
910
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200911 rectangles = pixman_region32_rectangles(&gs->texture_damage, &n);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400912 for (i = 0; i < n; i++) {
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200913 pixman_box32_t r;
914
915 r = weston_surface_to_buffer_rect(surface, rectangles[i]);
916
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700917 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, r.x1);
918 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, r.y1);
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200919 glTexSubImage2D(GL_TEXTURE_2D, 0, r.x1, r.y1,
920 r.x2 - r.x1, r.y2 - r.y1,
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200921 format, pixel_type, data);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400922 }
923#endif
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200924
925done:
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200926 pixman_region32_fini(&gs->texture_damage);
927 pixman_region32_init(&gs->texture_damage);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300928 gs->needs_full_upload = 0;
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200929
930 weston_buffer_reference(&gs->buffer_ref, NULL);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400931}
932
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400933static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100934ensure_textures(struct gl_surface_state *gs, int num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400935{
936 int i;
937
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100938 if (num_textures <= gs->num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400939 return;
940
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100941 for (i = gs->num_textures; i < num_textures; i++) {
942 glGenTextures(1, &gs->textures[i]);
943 glBindTexture(gs->target, gs->textures[i]);
944 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400945 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100946 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400947 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
948 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100949 gs->num_textures = num_textures;
950 glBindTexture(gs->target, 0);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400951}
952
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400953static void
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +0300954gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
955 struct wl_shm_buffer *shm_buffer)
956{
957 struct weston_compositor *ec = es->compositor;
958 struct gl_renderer *gr = get_renderer(ec);
959 struct gl_surface_state *gs = get_surface_state(es);
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200960 int pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +0300961
962 buffer->shm_buffer = shm_buffer;
963 buffer->width = wl_shm_buffer_get_width(shm_buffer);
964 buffer->height = wl_shm_buffer_get_height(shm_buffer);
965
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200966 switch (wl_shm_buffer_get_format(shm_buffer)) {
967 case WL_SHM_FORMAT_XRGB8888:
968 gs->shader = &gr->texture_shader_rgbx;
969 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
970 break;
971 case WL_SHM_FORMAT_ARGB8888:
972 gs->shader = &gr->texture_shader_rgba;
973 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
974 break;
975 case WL_SHM_FORMAT_RGB565:
976 gs->shader = &gr->texture_shader_rgbx;
977 pitch = wl_shm_buffer_get_stride(shm_buffer) / 2;
978 break;
979 default:
980 weston_log("warning: unknown shm buffer format\n");
981 gs->shader = &gr->texture_shader_rgba;
982 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
983 }
984
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +0300985 /* Only allocate a texture if it doesn't match existing one.
986 * If a switch from DRM allocated buffer to a SHM buffer is
987 * happening, we need to allocate a new texture buffer. */
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200988 if (pitch != gs->pitch ||
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +0300989 buffer->height != gs->height ||
990 gs->buffer_type != BUFFER_TYPE_SHM) {
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200991 gs->pitch = pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +0300992 gs->height = buffer->height;
993 gs->target = GL_TEXTURE_2D;
994 gs->buffer_type = BUFFER_TYPE_SHM;
995 gs->needs_full_upload = 1;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +0400996 gs->y_inverted = 1;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +0300997
998 ensure_textures(gs, 1);
999 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
1000 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1001 gs->pitch, buffer->height, 0,
1002 GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
1003 }
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001004}
1005
1006static void
1007gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
1008 uint32_t format)
1009{
1010 struct weston_compositor *ec = es->compositor;
1011 struct gl_renderer *gr = get_renderer(ec);
1012 struct gl_surface_state *gs = get_surface_state(es);
1013 EGLint attribs[3];
1014 int i, num_planes;
1015
1016 buffer->legacy_buffer = (struct wl_buffer *)buffer->resource;
1017 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1018 EGL_WIDTH, &buffer->width);
1019 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1020 EGL_HEIGHT, &buffer->height);
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001021 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1022 EGL_WAYLAND_Y_INVERTED_WL, &buffer->y_inverted);
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001023
1024 for (i = 0; i < gs->num_images; i++)
1025 gr->destroy_image(gr->egl_display, gs->images[i]);
1026 gs->num_images = 0;
1027 gs->target = GL_TEXTURE_2D;
1028 switch (format) {
1029 case EGL_TEXTURE_RGB:
1030 case EGL_TEXTURE_RGBA:
1031 default:
1032 num_planes = 1;
1033 gs->shader = &gr->texture_shader_rgba;
1034 break;
1035 case EGL_TEXTURE_EXTERNAL_WL:
1036 num_planes = 1;
1037 gs->target = GL_TEXTURE_EXTERNAL_OES;
1038 gs->shader = &gr->texture_shader_egl_external;
1039 break;
1040 case EGL_TEXTURE_Y_UV_WL:
1041 num_planes = 2;
1042 gs->shader = &gr->texture_shader_y_uv;
1043 break;
1044 case EGL_TEXTURE_Y_U_V_WL:
1045 num_planes = 3;
1046 gs->shader = &gr->texture_shader_y_u_v;
1047 break;
1048 case EGL_TEXTURE_Y_XUXV_WL:
1049 num_planes = 2;
1050 gs->shader = &gr->texture_shader_y_xuxv;
1051 break;
1052 }
1053
1054 ensure_textures(gs, num_planes);
1055 for (i = 0; i < num_planes; i++) {
1056 attribs[0] = EGL_WAYLAND_PLANE_WL;
1057 attribs[1] = i;
1058 attribs[2] = EGL_NONE;
1059 gs->images[i] = gr->create_image(gr->egl_display,
1060 NULL,
1061 EGL_WAYLAND_BUFFER_WL,
1062 buffer->legacy_buffer,
1063 attribs);
1064 if (!gs->images[i]) {
1065 weston_log("failed to create img for plane %d\n", i);
1066 continue;
1067 }
1068 gs->num_images++;
1069
1070 glActiveTexture(GL_TEXTURE0 + i);
1071 glBindTexture(gs->target, gs->textures[i]);
1072 gr->image_target_texture_2d(gs->target,
1073 gs->images[i]);
1074 }
1075
1076 gs->pitch = buffer->width;
1077 gs->height = buffer->height;
1078 gs->buffer_type = BUFFER_TYPE_EGL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001079 gs->y_inverted = buffer->y_inverted;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001080}
1081
1082static void
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001083gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001084{
1085 struct weston_compositor *ec = es->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001086 struct gl_renderer *gr = get_renderer(ec);
1087 struct gl_surface_state *gs = get_surface_state(es);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001088 struct wl_shm_buffer *shm_buffer;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001089 EGLint format;
1090 int i;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001091
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001092 weston_buffer_reference(&gs->buffer_ref, buffer);
1093
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001094 if (!buffer) {
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001095 for (i = 0; i < gs->num_images; i++) {
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001096 gr->destroy_image(gr->egl_display, gs->images[i]);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001097 gs->images[i] = NULL;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001098 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001099 gs->num_images = 0;
1100 glDeleteTextures(gs->num_textures, gs->textures);
1101 gs->num_textures = 0;
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001102 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001103 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001104 return;
1105 }
1106
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001107 shm_buffer = wl_shm_buffer_get(buffer->resource);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001108
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001109 if (shm_buffer)
1110 gl_renderer_attach_shm(es, buffer, shm_buffer);
Kristian Høgsberg47229392013-08-07 11:59:54 -07001111 else if (gr->query_buffer(gr->egl_display, (void *) buffer->resource,
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001112 EGL_TEXTURE_FORMAT, &format))
1113 gl_renderer_attach_egl(es, buffer, format);
1114 else {
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001115 weston_log("unhandled buffer type!\n");
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001116 weston_buffer_reference(&gs->buffer_ref, NULL);
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001117 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001118 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001119 }
1120}
1121
Kristian Høgsberg42263852012-09-06 21:59:29 -04001122static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001123gl_renderer_surface_set_color(struct weston_surface *surface,
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001124 float red, float green, float blue, float alpha)
1125{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001126 struct gl_surface_state *gs = get_surface_state(surface);
1127 struct gl_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001128
1129 gs->color[0] = red;
1130 gs->color[1] = green;
1131 gs->color[2] = blue;
1132 gs->color[3] = alpha;
1133
John Kåre Alsaker40684142012-11-13 19:10:25 +01001134 gs->shader = &gr->solid_shader;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001135}
1136
1137static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001138gl_renderer_create_surface(struct weston_surface *surface)
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001139{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001140 struct gl_surface_state *gs;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001141
1142 gs = calloc(1, sizeof *gs);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001143 if (!gs)
1144 return -1;
1145
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001146 /* A buffer is never attached to solid color surfaces, yet
1147 * they still go through texcoord computations. Do not divide
1148 * by zero there.
1149 */
1150 gs->pitch = 1;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001151 gs->y_inverted = 1;
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001152
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001153 pixman_region32_init(&gs->texture_damage);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001154 surface->renderer_state = gs;
1155
1156 return 0;
1157}
1158
1159static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001160gl_renderer_destroy_surface(struct weston_surface *surface)
Kristian Høgsberg42263852012-09-06 21:59:29 -04001161{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001162 struct gl_surface_state *gs = get_surface_state(surface);
1163 struct gl_renderer *gr = get_renderer(surface->compositor);
Kristian Høgsberg42263852012-09-06 21:59:29 -04001164 int i;
1165
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001166 glDeleteTextures(gs->num_textures, gs->textures);
Kristian Høgsberg42263852012-09-06 21:59:29 -04001167
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001168 for (i = 0; i < gs->num_images; i++)
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001169 gr->destroy_image(gr->egl_display, gs->images[i]);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001170
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001171 weston_buffer_reference(&gs->buffer_ref, NULL);
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001172 pixman_region32_fini(&gs->texture_damage);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001173 free(gs);
Kristian Høgsberg42263852012-09-06 21:59:29 -04001174}
1175
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001176static const char vertex_shader[] =
1177 "uniform mat4 proj;\n"
1178 "attribute vec2 position;\n"
1179 "attribute vec2 texcoord;\n"
1180 "varying vec2 v_texcoord;\n"
1181 "void main()\n"
1182 "{\n"
1183 " gl_Position = proj * vec4(position, 0.0, 1.0);\n"
1184 " v_texcoord = texcoord;\n"
1185 "}\n";
1186
1187/* Declare common fragment shader uniforms */
1188#define FRAGMENT_CONVERT_YUV \
1189 " y *= alpha;\n" \
1190 " u *= alpha;\n" \
1191 " v *= alpha;\n" \
1192 " gl_FragColor.r = y + 1.59602678 * v;\n" \
1193 " gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n" \
1194 " gl_FragColor.b = y + 2.01723214 * u;\n" \
1195 " gl_FragColor.a = alpha;\n"
1196
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001197static const char fragment_debug[] =
1198 " gl_FragColor = vec4(0.0, 0.3, 0.0, 0.2) + gl_FragColor * 0.8;\n";
1199
1200static const char fragment_brace[] =
1201 "}\n";
1202
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001203static const char texture_fragment_shader_rgba[] =
1204 "precision mediump float;\n"
1205 "varying vec2 v_texcoord;\n"
1206 "uniform sampler2D tex;\n"
1207 "uniform float alpha;\n"
1208 "void main()\n"
1209 "{\n"
1210 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001211 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001212
1213static const char texture_fragment_shader_rgbx[] =
1214 "precision mediump float;\n"
1215 "varying vec2 v_texcoord;\n"
1216 "uniform sampler2D tex;\n"
1217 "uniform float alpha;\n"
1218 "void main()\n"
1219 "{\n"
1220 " gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb\n;"
1221 " gl_FragColor.a = alpha;\n"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001222 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001223
1224static const char texture_fragment_shader_egl_external[] =
1225 "#extension GL_OES_EGL_image_external : require\n"
1226 "precision mediump float;\n"
1227 "varying vec2 v_texcoord;\n"
1228 "uniform samplerExternalOES tex;\n"
1229 "uniform float alpha;\n"
1230 "void main()\n"
1231 "{\n"
1232 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001233 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001234
1235static const char texture_fragment_shader_y_uv[] =
1236 "precision mediump float;\n"
1237 "uniform sampler2D tex;\n"
1238 "uniform sampler2D tex1;\n"
1239 "varying vec2 v_texcoord;\n"
1240 "uniform float alpha;\n"
1241 "void main() {\n"
1242 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1243 " float u = texture2D(tex1, v_texcoord).r - 0.5;\n"
1244 " float v = texture2D(tex1, v_texcoord).g - 0.5;\n"
1245 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001246 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001247
1248static const char texture_fragment_shader_y_u_v[] =
1249 "precision mediump float;\n"
1250 "uniform sampler2D tex;\n"
1251 "uniform sampler2D tex1;\n"
1252 "uniform sampler2D tex2;\n"
1253 "varying vec2 v_texcoord;\n"
1254 "uniform float alpha;\n"
1255 "void main() {\n"
1256 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1257 " float u = texture2D(tex1, v_texcoord).x - 0.5;\n"
1258 " float v = texture2D(tex2, v_texcoord).x - 0.5;\n"
1259 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001260 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001261
1262static const char texture_fragment_shader_y_xuxv[] =
1263 "precision mediump float;\n"
1264 "uniform sampler2D tex;\n"
1265 "uniform sampler2D tex1;\n"
1266 "varying vec2 v_texcoord;\n"
1267 "uniform float alpha;\n"
1268 "void main() {\n"
1269 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1270 " float u = texture2D(tex1, v_texcoord).g - 0.5;\n"
1271 " float v = texture2D(tex1, v_texcoord).a - 0.5;\n"
1272 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001273 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001274
1275static const char solid_fragment_shader[] =
1276 "precision mediump float;\n"
1277 "uniform vec4 color;\n"
1278 "uniform float alpha;\n"
1279 "void main()\n"
1280 "{\n"
1281 " gl_FragColor = alpha * color\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001282 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001283
1284static int
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001285compile_shader(GLenum type, int count, const char **sources)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001286{
1287 GLuint s;
1288 char msg[512];
1289 GLint status;
1290
1291 s = glCreateShader(type);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001292 glShaderSource(s, count, sources, NULL);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001293 glCompileShader(s);
1294 glGetShaderiv(s, GL_COMPILE_STATUS, &status);
1295 if (!status) {
1296 glGetShaderInfoLog(s, sizeof msg, NULL, msg);
1297 weston_log("shader info: %s\n", msg);
1298 return GL_NONE;
1299 }
1300
1301 return s;
1302}
1303
1304static int
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03001305shader_init(struct gl_shader *shader, struct gl_renderer *renderer,
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001306 const char *vertex_source, const char *fragment_source)
1307{
1308 char msg[512];
1309 GLint status;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001310 int count;
1311 const char *sources[3];
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001312
1313 shader->vertex_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001314 compile_shader(GL_VERTEX_SHADER, 1, &vertex_source);
1315
1316 if (renderer->fragment_shader_debug) {
1317 sources[0] = fragment_source;
1318 sources[1] = fragment_debug;
1319 sources[2] = fragment_brace;
1320 count = 3;
1321 } else {
1322 sources[0] = fragment_source;
1323 sources[1] = fragment_brace;
1324 count = 2;
1325 }
1326
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001327 shader->fragment_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001328 compile_shader(GL_FRAGMENT_SHADER, count, sources);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001329
1330 shader->program = glCreateProgram();
1331 glAttachShader(shader->program, shader->vertex_shader);
1332 glAttachShader(shader->program, shader->fragment_shader);
1333 glBindAttribLocation(shader->program, 0, "position");
1334 glBindAttribLocation(shader->program, 1, "texcoord");
1335
1336 glLinkProgram(shader->program);
1337 glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
1338 if (!status) {
1339 glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
1340 weston_log("link info: %s\n", msg);
1341 return -1;
1342 }
1343
1344 shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
1345 shader->tex_uniforms[0] = glGetUniformLocation(shader->program, "tex");
1346 shader->tex_uniforms[1] = glGetUniformLocation(shader->program, "tex1");
1347 shader->tex_uniforms[2] = glGetUniformLocation(shader->program, "tex2");
1348 shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
1349 shader->color_uniform = glGetUniformLocation(shader->program, "color");
1350
1351 return 0;
1352}
1353
1354static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001355shader_release(struct gl_shader *shader)
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001356{
1357 glDeleteShader(shader->vertex_shader);
1358 glDeleteShader(shader->fragment_shader);
1359 glDeleteProgram(shader->program);
1360
1361 shader->vertex_shader = 0;
1362 shader->fragment_shader = 0;
1363 shader->program = 0;
1364}
1365
1366static void
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001367log_extensions(const char *name, const char *extensions)
1368{
1369 const char *p, *end;
1370 int l;
1371 int len;
1372
1373 l = weston_log("%s:", name);
1374 p = extensions;
1375 while (*p) {
1376 end = strchrnul(p, ' ');
1377 len = end - p;
1378 if (l + len > 78)
1379 l = weston_log_continue("\n" STAMP_SPACE "%.*s",
1380 len, p);
1381 else
1382 l += weston_log_continue(" %.*s", len, p);
1383 for (p = end; isspace(*p); p++)
1384 ;
1385 }
1386 weston_log_continue("\n");
1387}
1388
1389static void
1390log_egl_gl_info(EGLDisplay egldpy)
1391{
1392 const char *str;
1393
1394 str = eglQueryString(egldpy, EGL_VERSION);
1395 weston_log("EGL version: %s\n", str ? str : "(null)");
1396
1397 str = eglQueryString(egldpy, EGL_VENDOR);
1398 weston_log("EGL vendor: %s\n", str ? str : "(null)");
1399
1400 str = eglQueryString(egldpy, EGL_CLIENT_APIS);
1401 weston_log("EGL client APIs: %s\n", str ? str : "(null)");
1402
1403 str = eglQueryString(egldpy, EGL_EXTENSIONS);
1404 log_extensions("EGL extensions", str ? str : "(null)");
1405
1406 str = (char *)glGetString(GL_VERSION);
1407 weston_log("GL version: %s\n", str ? str : "(null)");
1408
1409 str = (char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
1410 weston_log("GLSL version: %s\n", str ? str : "(null)");
1411
1412 str = (char *)glGetString(GL_VENDOR);
1413 weston_log("GL vendor: %s\n", str ? str : "(null)");
1414
1415 str = (char *)glGetString(GL_RENDERER);
1416 weston_log("GL renderer: %s\n", str ? str : "(null)");
1417
1418 str = (char *)glGetString(GL_EXTENSIONS);
1419 log_extensions("GL extensions", str ? str : "(null)");
1420}
1421
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001422static void
1423log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
1424{
1425 EGLint r, g, b, a;
1426
1427 weston_log("Chosen EGL config details:\n");
1428
1429 weston_log_continue(STAMP_SPACE "RGBA bits");
1430 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_RED_SIZE, &r) &&
1431 eglGetConfigAttrib(egldpy, eglconfig, EGL_GREEN_SIZE, &g) &&
1432 eglGetConfigAttrib(egldpy, eglconfig, EGL_BLUE_SIZE, &b) &&
1433 eglGetConfigAttrib(egldpy, eglconfig, EGL_ALPHA_SIZE, &a))
1434 weston_log_continue(": %d %d %d %d\n", r, g, b, a);
1435 else
1436 weston_log_continue(" unknown\n");
1437
1438 weston_log_continue(STAMP_SPACE "swap interval range");
1439 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_MIN_SWAP_INTERVAL, &a) &&
1440 eglGetConfigAttrib(egldpy, eglconfig, EGL_MAX_SWAP_INTERVAL, &b))
1441 weston_log_continue(": %d - %d\n", a, b);
1442 else
1443 weston_log_continue(" unknown\n");
1444}
1445
John Kåre Alsaker44154502012-11-13 19:10:20 +01001446static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001447output_apply_border(struct weston_output *output, struct gl_renderer *gr)
John Kåre Alsaker44154502012-11-13 19:10:20 +01001448{
1449 output->border.top = gr->border.top;
1450 output->border.bottom = gr->border.bottom;
1451 output->border.left = gr->border.left;
1452 output->border.right = gr->border.right;
1453}
1454
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001455static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001456gl_renderer_set_border(struct weston_compositor *ec, int32_t width, int32_t height, void *data,
John Kåre Alsaker44154502012-11-13 19:10:20 +01001457 int32_t *edges)
1458{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001459 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker44154502012-11-13 19:10:20 +01001460 struct weston_output *output;
1461
1462 gr->border.left = edges[0];
1463 gr->border.right = edges[1];
1464 gr->border.top = edges[2];
1465 gr->border.bottom = edges[3];
1466
1467 gr->border.width = width;
1468 gr->border.height = height;
1469
1470 glGenTextures(1, &gr->border.texture);
1471 glBindTexture(GL_TEXTURE_2D, gr->border.texture);
1472 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1473 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1474 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1475 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1476
1477 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1478 width,
1479 height,
1480 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
1481 data);
1482
1483 wl_list_for_each(output, &ec->output_list, link)
1484 output_apply_border(output, gr);
1485}
1486
John Kåre Alsaker94659272012-11-13 19:10:18 +01001487static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001488gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001489
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001490static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001491gl_renderer_output_create(struct weston_output *output,
John Kåre Alsaker94659272012-11-13 19:10:18 +01001492 EGLNativeWindowType window)
1493{
1494 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001495 struct gl_renderer *gr = get_renderer(ec);
1496 struct gl_output_state *go = calloc(1, sizeof *go);
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001497 int i;
John Kåre Alsaker94659272012-11-13 19:10:18 +01001498
1499 if (!go)
1500 return -1;
1501
1502 go->egl_surface =
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001503 eglCreateWindowSurface(gr->egl_display,
1504 gr->egl_config,
John Kåre Alsaker94659272012-11-13 19:10:18 +01001505 window, NULL);
1506
1507 if (go->egl_surface == EGL_NO_SURFACE) {
1508 weston_log("failed to create egl surface\n");
1509 free(go);
1510 return -1;
1511 }
1512
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001513 if (gr->egl_context == NULL)
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001514 if (gl_renderer_setup(ec, go->egl_surface) < 0) {
John Kåre Alsaker94659272012-11-13 19:10:18 +01001515 free(go);
1516 return -1;
1517 }
1518
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001519 for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001520 pixman_region32_init(&go->buffer_damage[i]);
1521
John Kåre Alsaker94659272012-11-13 19:10:18 +01001522 output->renderer_state = go;
1523
John Kåre Alsaker44154502012-11-13 19:10:20 +01001524 output_apply_border(output, gr);
1525
John Kåre Alsaker94659272012-11-13 19:10:18 +01001526 return 0;
1527}
1528
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001529static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001530gl_renderer_output_destroy(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01001531{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001532 struct gl_renderer *gr = get_renderer(output->compositor);
1533 struct gl_output_state *go = get_output_state(output);
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001534 int i;
1535
1536 for (i = 0; i < 2; i++)
1537 pixman_region32_fini(&go->buffer_damage[i]);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001538
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001539 eglDestroySurface(gr->egl_display, go->egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001540
1541 free(go);
1542}
1543
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001544static EGLSurface
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001545gl_renderer_output_surface(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01001546{
1547 return get_output_state(output)->egl_surface;
1548}
1549
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03001550static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001551gl_renderer_destroy(struct weston_compositor *ec)
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001552{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001553 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001554
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001555 if (gr->has_bind_display)
1556 gr->unbind_display(gr->egl_display, ec->wl_display);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001557
1558 /* Work around crash in egl_dri2.c's dri2_make_current() - when does this apply? */
1559 eglMakeCurrent(gr->egl_display,
1560 EGL_NO_SURFACE, EGL_NO_SURFACE,
1561 EGL_NO_CONTEXT);
1562
1563 eglTerminate(gr->egl_display);
1564 eglReleaseThread();
Scott Moreau976a0502013-03-07 10:15:17 -07001565
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -04001566 wl_array_release(&gr->vertices);
1567 wl_array_release(&gr->indices);
1568 wl_array_release(&gr->vtxcnt);
1569
Scott Moreau976a0502013-03-07 10:15:17 -07001570 free(gr);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001571}
1572
1573static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001574egl_choose_config(struct gl_renderer *gr, const EGLint *attribs,
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001575 const EGLint *visual_id)
1576{
1577 EGLint count = 0;
1578 EGLint matched = 0;
1579 EGLConfig *configs;
1580 int i;
1581
1582 if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1)
1583 return -1;
1584
1585 configs = calloc(count, sizeof *configs);
1586 if (!configs)
1587 return -1;
1588
1589 if (!eglChooseConfig(gr->egl_display, attribs, configs,
1590 count, &matched))
1591 goto out;
1592
1593 for (i = 0; i < matched; ++i) {
1594 EGLint id;
1595
1596 if (visual_id) {
1597 if (!eglGetConfigAttrib(gr->egl_display,
1598 configs[i], EGL_NATIVE_VISUAL_ID,
1599 &id))
1600 continue;
1601
Kristian Høgsbergc3ea26c2013-09-25 15:46:42 -07001602 if (id != 0 && id != *visual_id)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001603 continue;
1604 }
1605
1606 gr->egl_config = configs[i];
1607
1608 free(configs);
1609 return 0;
1610 }
1611
1612out:
1613 free(configs);
1614 return -1;
1615}
1616
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001617static const EGLint gl_renderer_opaque_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001618 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1619 EGL_RED_SIZE, 1,
1620 EGL_GREEN_SIZE, 1,
1621 EGL_BLUE_SIZE, 1,
1622 EGL_ALPHA_SIZE, 0,
1623 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1624 EGL_NONE
1625};
1626
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001627static const EGLint gl_renderer_alpha_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001628 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1629 EGL_RED_SIZE, 1,
1630 EGL_GREEN_SIZE, 1,
1631 EGL_BLUE_SIZE, 1,
1632 EGL_ALPHA_SIZE, 1,
1633 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1634 EGL_NONE
1635};
1636
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001637static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001638gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001639 const EGLint *attribs, const EGLint *visual_id)
1640{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001641 struct gl_renderer *gr;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001642 EGLint major, minor;
1643
1644 gr = calloc(1, sizeof *gr);
1645
1646 if (gr == NULL)
1647 return -1;
1648
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001649 gr->base.read_pixels = gl_renderer_read_pixels;
1650 gr->base.repaint_output = gl_renderer_repaint_output;
1651 gr->base.flush_damage = gl_renderer_flush_damage;
1652 gr->base.attach = gl_renderer_attach;
1653 gr->base.create_surface = gl_renderer_create_surface;
1654 gr->base.surface_set_color = gl_renderer_surface_set_color;
1655 gr->base.destroy_surface = gl_renderer_destroy_surface;
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03001656 gr->base.destroy = gl_renderer_destroy;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001657
1658 gr->egl_display = eglGetDisplay(display);
1659 if (gr->egl_display == EGL_NO_DISPLAY) {
1660 weston_log("failed to create display\n");
1661 goto err_egl;
1662 }
1663
1664 if (!eglInitialize(gr->egl_display, &major, &minor)) {
1665 weston_log("failed to initialize display\n");
1666 goto err_egl;
1667 }
1668
1669 if (egl_choose_config(gr, attribs, visual_id) < 0) {
1670 weston_log("failed to choose EGL config\n");
1671 goto err_egl;
1672 }
1673
1674 ec->renderer = &gr->base;
Pekka Paalanen7bb65102013-05-22 18:03:04 +03001675 ec->capabilities |= WESTON_CAP_ROTATION_ANY;
Pekka Paalanen4fc5dd02013-05-22 18:03:05 +03001676 ec->capabilities |= WESTON_CAP_CAPTURE_YFLIP;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001677
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001678 wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565);
1679
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001680 return 0;
1681
1682err_egl:
Pekka Paalanen326529f2012-11-27 12:25:25 +02001683 gl_renderer_print_egl_error_state();
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001684 free(gr);
1685 return -1;
1686}
1687
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001688static EGLDisplay
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001689gl_renderer_display(struct weston_compositor *ec)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001690{
1691 return get_renderer(ec)->egl_display;
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001692}
1693
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001694static int
1695compile_shaders(struct weston_compositor *ec)
1696{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001697 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker40684142012-11-13 19:10:25 +01001698
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03001699 gr->texture_shader_rgba.vertex_source = vertex_shader;
1700 gr->texture_shader_rgba.fragment_source = texture_fragment_shader_rgba;
1701
1702 gr->texture_shader_rgbx.vertex_source = vertex_shader;
1703 gr->texture_shader_rgbx.fragment_source = texture_fragment_shader_rgbx;
1704
1705 gr->texture_shader_egl_external.vertex_source = vertex_shader;
1706 gr->texture_shader_egl_external.fragment_source =
1707 texture_fragment_shader_egl_external;
1708
1709 gr->texture_shader_y_uv.vertex_source = vertex_shader;
1710 gr->texture_shader_y_uv.fragment_source = texture_fragment_shader_y_uv;
1711
1712 gr->texture_shader_y_u_v.vertex_source = vertex_shader;
1713 gr->texture_shader_y_u_v.fragment_source =
1714 texture_fragment_shader_y_u_v;
1715
1716 gr->texture_shader_y_u_v.vertex_source = vertex_shader;
1717 gr->texture_shader_y_xuxv.fragment_source =
1718 texture_fragment_shader_y_xuxv;
1719
1720 gr->solid_shader.vertex_source = vertex_shader;
1721 gr->solid_shader.fragment_source = solid_fragment_shader;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001722
1723 return 0;
1724}
1725
1726static void
Kristian Høgsberge3148752013-05-06 23:19:49 -04001727fragment_debug_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001728 void *data)
1729{
1730 struct weston_compositor *ec = data;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001731 struct gl_renderer *gr = get_renderer(ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001732 struct weston_output *output;
1733
John Kåre Alsaker40684142012-11-13 19:10:25 +01001734 gr->fragment_shader_debug ^= 1;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001735
John Kåre Alsaker40684142012-11-13 19:10:25 +01001736 shader_release(&gr->texture_shader_rgba);
1737 shader_release(&gr->texture_shader_rgbx);
1738 shader_release(&gr->texture_shader_egl_external);
1739 shader_release(&gr->texture_shader_y_uv);
1740 shader_release(&gr->texture_shader_y_u_v);
1741 shader_release(&gr->texture_shader_y_xuxv);
1742 shader_release(&gr->solid_shader);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001743
Ander Conselvan de Oliveira03fb4ef2012-12-03 17:08:11 +02001744 /* Force use_shader() to call glUseProgram(), since we need to use
1745 * the recompiled version of the shader. */
1746 gr->current_shader = NULL;
1747
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001748 wl_list_for_each(output, &ec->output_list, link)
1749 weston_output_damage(output);
1750}
1751
Kristian Høgsberg8799d412013-05-07 10:50:09 -04001752static void
1753fan_debug_repaint_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
1754 void *data)
1755{
1756 struct weston_compositor *compositor = data;
1757 struct gl_renderer *gr = get_renderer(compositor);
1758
1759 gr->fan_debug = !gr->fan_debug;
1760 weston_compositor_damage_all(compositor);
1761}
1762
John Kåre Alsaker94659272012-11-13 19:10:18 +01001763static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001764gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001765{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001766 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001767 const char *extensions;
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001768 EGLBoolean ret;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001769
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001770 static const EGLint context_attribs[] = {
1771 EGL_CONTEXT_CLIENT_VERSION, 2,
1772 EGL_NONE
1773 };
1774
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001775 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
1776 weston_log("failed to bind EGL_OPENGL_ES_API\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001777 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001778 return -1;
1779 }
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001780
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001781 log_egl_config_info(gr->egl_display, gr->egl_config);
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001782
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001783 gr->egl_context = eglCreateContext(gr->egl_display, gr->egl_config,
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001784 EGL_NO_CONTEXT, context_attribs);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001785 if (gr->egl_context == NULL) {
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001786 weston_log("failed to create context\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001787 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001788 return -1;
1789 }
1790
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001791 ret = eglMakeCurrent(gr->egl_display, egl_surface,
1792 egl_surface, gr->egl_context);
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001793 if (ret == EGL_FALSE) {
1794 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001795 gl_renderer_print_egl_error_state();
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001796 return -1;
1797 }
1798
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001799 log_egl_gl_info(gr->egl_display);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001800
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001801 gr->image_target_texture_2d =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001802 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001803 gr->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
1804 gr->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
1805 gr->bind_display =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001806 (void *) eglGetProcAddress("eglBindWaylandDisplayWL");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001807 gr->unbind_display =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001808 (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001809 gr->query_buffer =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001810 (void *) eglGetProcAddress("eglQueryWaylandBufferWL");
1811
1812 extensions = (const char *) glGetString(GL_EXTENSIONS);
1813 if (!extensions) {
1814 weston_log("Retrieving GL extension string failed.\n");
1815 return -1;
1816 }
1817
1818 if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
1819 weston_log("GL_EXT_texture_format_BGRA8888 not available\n");
1820 return -1;
1821 }
1822
1823 if (strstr(extensions, "GL_EXT_read_format_bgra"))
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01001824 ec->read_format = PIXMAN_a8r8g8b8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001825 else
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01001826 ec->read_format = PIXMAN_a8b8g8r8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001827
Kristian Høgsberg1c4f1632013-08-07 12:11:27 -07001828#ifdef GL_EXT_unpack_subimage
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001829 if (strstr(extensions, "GL_EXT_unpack_subimage"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001830 gr->has_unpack_subimage = 1;
Kristian Høgsberg1c4f1632013-08-07 12:11:27 -07001831#endif
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001832
1833 if (strstr(extensions, "GL_OES_EGL_image_external"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001834 gr->has_egl_image_external = 1;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001835
1836 extensions =
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001837 (const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001838 if (!extensions) {
1839 weston_log("Retrieving EGL extension string failed.\n");
1840 return -1;
1841 }
1842
1843 if (strstr(extensions, "EGL_WL_bind_wayland_display"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001844 gr->has_bind_display = 1;
1845 if (gr->has_bind_display) {
1846 ret = gr->bind_display(gr->egl_display, ec->wl_display);
Pekka Paalanen035a0322012-10-24 09:43:06 +03001847 if (!ret)
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001848 gr->has_bind_display = 0;
Pekka Paalanen035a0322012-10-24 09:43:06 +03001849 }
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001850
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001851 if (strstr(extensions, "EGL_EXT_buffer_age"))
1852 gr->has_egl_buffer_age = 1;
1853 else
1854 weston_log("warning: EGL_EXT_buffer_age not supported. "
1855 "Performance could be affected.\n");
1856
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001857 glActiveTexture(GL_TEXTURE0);
1858
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001859 if (compile_shaders(ec))
1860 return -1;
1861
1862 weston_compositor_add_debug_binding(ec, KEY_S,
1863 fragment_debug_binding, ec);
Kristian Høgsberg8799d412013-05-07 10:50:09 -04001864 weston_compositor_add_debug_binding(ec, KEY_F,
1865 fan_debug_repaint_binding, ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001866
Pekka Paalanen035a0322012-10-24 09:43:06 +03001867 weston_log("GL ES 2 renderer features:\n");
1868 weston_log_continue(STAMP_SPACE "read-back format: %s\n",
Pekka Paalanenfe4eacf2013-01-10 16:50:42 +02001869 ec->read_format == PIXMAN_a8r8g8b8 ? "BGRA" : "RGBA");
Pekka Paalanen035a0322012-10-24 09:43:06 +03001870 weston_log_continue(STAMP_SPACE "wl_shm sub-image to texture: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001871 gr->has_unpack_subimage ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03001872 weston_log_continue(STAMP_SPACE "EGL Wayland extension: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001873 gr->has_bind_display ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03001874
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001875
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001876 return 0;
1877}
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001878
1879WL_EXPORT struct gl_renderer_interface gl_renderer_interface = {
1880 .opaque_attribs = gl_renderer_opaque_attribs,
1881 .alpha_attribs = gl_renderer_alpha_attribs,
1882
1883 .create = gl_renderer_create,
1884 .display = gl_renderer_display,
1885 .output_create = gl_renderer_output_create,
1886 .output_destroy = gl_renderer_output_destroy,
1887 .output_surface = gl_renderer_output_surface,
1888 .set_border = gl_renderer_set_border,
1889 .print_egl_error_state = gl_renderer_print_egl_error_state
1890};