blob: 0f0b5f74495adaa9ed6b949051ae3ea4ad63348e [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;
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +030088 struct weston_binding *fragment_binding;
89 struct weston_binding *fan_binding;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +010090
91 EGLDisplay egl_display;
92 EGLContext egl_context;
93 EGLConfig egl_config;
John Kåre Alsaker44154502012-11-13 19:10:20 +010094
95 struct {
96 int32_t top, bottom, left, right;
97 GLuint texture;
98 int32_t width, height;
99 } border;
John Kåre Alsaker40684142012-11-13 19:10:25 +0100100
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400101 struct wl_array vertices;
102 struct wl_array indices; /* only used in compositor-wayland */
103 struct wl_array vtxcnt;
104
John Kåre Alsaker320711d2012-11-13 19:10:27 +0100105 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
106 PFNEGLCREATEIMAGEKHRPROC create_image;
107 PFNEGLDESTROYIMAGEKHRPROC destroy_image;
108
109 int has_unpack_subimage;
110
111 PFNEGLBINDWAYLANDDISPLAYWL bind_display;
112 PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
113 PFNEGLQUERYWAYLANDBUFFERWL query_buffer;
114 int has_bind_display;
115
116 int has_egl_image_external;
117
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200118 int has_egl_buffer_age;
119
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100120 struct gl_shader texture_shader_rgba;
121 struct gl_shader texture_shader_rgbx;
122 struct gl_shader texture_shader_egl_external;
123 struct gl_shader texture_shader_y_uv;
124 struct gl_shader texture_shader_y_u_v;
125 struct gl_shader texture_shader_y_xuxv;
126 struct gl_shader invert_color_shader;
127 struct gl_shader solid_shader;
128 struct gl_shader *current_shader;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100129};
John Kåre Alsaker94659272012-11-13 19:10:18 +0100130
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100131static inline struct gl_output_state *
John Kåre Alsaker94659272012-11-13 19:10:18 +0100132get_output_state(struct weston_output *output)
133{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100134 return (struct gl_output_state *)output->renderer_state;
John Kåre Alsaker94659272012-11-13 19:10:18 +0100135}
136
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100137static inline struct gl_surface_state *
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100138get_surface_state(struct weston_surface *surface)
139{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100140 return (struct gl_surface_state *)surface->renderer_state;
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100141}
142
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100143static inline struct gl_renderer *
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100144get_renderer(struct weston_compositor *ec)
145{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100146 return (struct gl_renderer *)ec->renderer;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100147}
148
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400149static const char *
150egl_error_string(EGLint code)
151{
152#define MYERRCODE(x) case x: return #x;
153 switch (code) {
154 MYERRCODE(EGL_SUCCESS)
155 MYERRCODE(EGL_NOT_INITIALIZED)
156 MYERRCODE(EGL_BAD_ACCESS)
157 MYERRCODE(EGL_BAD_ALLOC)
158 MYERRCODE(EGL_BAD_ATTRIBUTE)
159 MYERRCODE(EGL_BAD_CONTEXT)
160 MYERRCODE(EGL_BAD_CONFIG)
161 MYERRCODE(EGL_BAD_CURRENT_SURFACE)
162 MYERRCODE(EGL_BAD_DISPLAY)
163 MYERRCODE(EGL_BAD_SURFACE)
164 MYERRCODE(EGL_BAD_MATCH)
165 MYERRCODE(EGL_BAD_PARAMETER)
166 MYERRCODE(EGL_BAD_NATIVE_PIXMAP)
167 MYERRCODE(EGL_BAD_NATIVE_WINDOW)
168 MYERRCODE(EGL_CONTEXT_LOST)
169 default:
170 return "unknown";
171 }
172#undef MYERRCODE
173}
174
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +0300175static void
Pekka Paalanen326529f2012-11-27 12:25:25 +0200176gl_renderer_print_egl_error_state(void)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400177{
178 EGLint code;
179
180 code = eglGetError();
181 weston_log("EGL error state: %s (0x%04lx)\n",
182 egl_error_string(code), (long)code);
183}
184
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400185#define max(a, b) (((a) > (b)) ? (a) : (b))
186#define min(a, b) (((a) > (b)) ? (b) : (a))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400187
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300188/*
189 * Compute the boundary vertices of the intersection of the global coordinate
190 * aligned rectangle 'rect', and an arbitrary quadrilateral produced from
191 * 'surf_rect' when transformed from surface coordinates into global coordinates.
192 * The vertices are written to 'ex' and 'ey', and the return value is the
193 * number of vertices. Vertices are produced in clockwise winding order.
194 * Guarantees to produce either zero vertices, or 3-8 vertices with non-zero
195 * polygon area.
196 */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400197static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500198calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400199 pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
200{
Sam Spilsbury619859c2013-09-13 10:01:21 +0800201
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300202 struct clip_context ctx;
203 int i, n;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400204 GLfloat min_x, max_x, min_y, max_y;
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300205 struct polygon8 surf = {
206 { surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1 },
207 { surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2 },
208 4
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400209 };
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400210
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300211 ctx.clip.x1 = rect->x1;
212 ctx.clip.y1 = rect->y1;
213 ctx.clip.x2 = rect->x2;
214 ctx.clip.y2 = rect->y2;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400215
216 /* transform surface to screen space: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300217 for (i = 0; i < surf.n; i++)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500218 weston_view_to_global_float(ev, surf.x[i], surf.y[i],
219 &surf.x[i], &surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400220
221 /* find bounding box: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300222 min_x = max_x = surf.x[0];
223 min_y = max_y = surf.y[0];
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400224
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300225 for (i = 1; i < surf.n; i++) {
226 min_x = min(min_x, surf.x[i]);
227 max_x = max(max_x, surf.x[i]);
228 min_y = min(min_y, surf.y[i]);
229 max_y = max(max_y, surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400230 }
231
232 /* First, simple bounding box check to discard early transformed
233 * surface rects that do not intersect with the clip region:
234 */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300235 if ((min_x >= ctx.clip.x2) || (max_x <= ctx.clip.x1) ||
236 (min_y >= ctx.clip.y2) || (max_y <= ctx.clip.y1))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400237 return 0;
238
239 /* Simple case, bounding box edges are parallel to surface edges,
240 * there will be only four edges. We just need to clip the surface
241 * vertices to the clip rect bounds:
242 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500243 if (!ev->transform.enabled)
Sam Spilsbury619859c2013-09-13 10:01:21 +0800244 return clip_simple(&ctx, &surf, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400245
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300246 /* Transformed case: use a general polygon clipping algorithm to
247 * clip the surface rectangle with each side of 'rect'.
248 * The algorithm is Sutherland-Hodgman, as explained in
249 * http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm
250 * but without looking at any of that code.
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400251 */
Sam Spilsbury619859c2013-09-13 10:01:21 +0800252 n = clip_transformed(&ctx, &surf, ex, ey);
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300253
254 if (n < 3)
255 return 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400256
257 return n;
258}
259
260static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500261texture_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400262 pixman_region32_t *surf_region)
263{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500264 struct gl_surface_state *gs = get_surface_state(ev->surface);
265 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400266 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400267 GLfloat *v, inv_width, inv_height;
268 unsigned int *vtxcnt, nvtx = 0;
269 pixman_box32_t *rects, *surf_rects;
270 int i, j, k, nrects, nsurf;
271
272 rects = pixman_region32_rectangles(region, &nrects);
273 surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
274
275 /* worst case we can have 8 vertices per rect (ie. clipped into
276 * an octagon):
277 */
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400278 v = wl_array_add(&gr->vertices, nrects * nsurf * 8 * 4 * sizeof *v);
279 vtxcnt = wl_array_add(&gr->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400280
Pekka Paalanen68033ac2012-12-04 15:58:15 +0200281 inv_width = 1.0 / gs->pitch;
Alexander Larsson4ea95522013-05-22 14:41:37 +0200282 inv_height = 1.0 / gs->height;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400283
284 for (i = 0; i < nrects; i++) {
285 pixman_box32_t *rect = &rects[i];
286 for (j = 0; j < nsurf; j++) {
287 pixman_box32_t *surf_rect = &surf_rects[j];
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200288 GLfloat sx, sy, bx, by;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400289 GLfloat ex[8], ey[8]; /* edge points in screen space */
290 int n;
291
292 /* The transformed surface, after clipping to the clip region,
293 * can have as many as eight sides, emitted as a triangle-fan.
294 * The first vertex in the triangle fan can be chosen arbitrarily,
295 * since the area is guaranteed to be convex.
296 *
297 * If a corner of the transformed surface falls outside of the
298 * clip region, instead of emitting one vertex for the corner
299 * of the surface, up to two are emitted for two corresponding
300 * intersection point(s) between the surface and the clip region.
301 *
302 * To do this, we first calculate the (up to eight) points that
303 * form the intersection of the clip rect and the transformed
304 * surface.
305 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500306 n = calculate_edges(ev, rect, surf_rect, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400307 if (n < 3)
308 continue;
309
310 /* emit edge points: */
311 for (k = 0; k < n; k++) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500312 weston_view_from_global_float(ev, ex[k], ey[k],
313 &sx, &sy);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400314 /* position: */
315 *(v++) = ex[k];
316 *(v++) = ey[k];
317 /* texcoord: */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500318 weston_surface_to_buffer_float(ev->surface,
319 sx, sy,
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200320 &bx, &by);
321 *(v++) = bx * inv_width;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +0400322 if (gs->y_inverted) {
323 *(v++) = by * inv_height;
324 } else {
325 *(v++) = (gs->height - by) * inv_height;
326 }
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400327 }
328
329 vtxcnt[nvtx++] = n;
330 }
331 }
332
333 return nvtx;
334}
335
336static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500337triangle_fan_debug(struct weston_view *view, int first, int count)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400338{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500339 struct weston_compositor *compositor = view->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100340 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400341 int i;
342 GLushort *buffer;
343 GLushort *index;
344 int nelems;
345 static int color_idx = 0;
346 static const GLfloat color[][4] = {
347 { 1.0, 0.0, 0.0, 1.0 },
348 { 0.0, 1.0, 0.0, 1.0 },
349 { 0.0, 0.0, 1.0, 1.0 },
350 { 1.0, 1.0, 1.0, 1.0 },
351 };
352
353 nelems = (count - 1 + count - 2) * 2;
354
355 buffer = malloc(sizeof(GLushort) * nelems);
356 index = buffer;
357
358 for (i = 1; i < count; i++) {
359 *index++ = first;
360 *index++ = first + i;
361 }
362
363 for (i = 2; i < count; i++) {
364 *index++ = first + i - 1;
365 *index++ = first + i;
366 }
367
John Kåre Alsaker40684142012-11-13 19:10:25 +0100368 glUseProgram(gr->solid_shader.program);
369 glUniform4fv(gr->solid_shader.color_uniform, 1,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400370 color[color_idx++ % ARRAY_LENGTH(color)]);
371 glDrawElements(GL_LINES, nelems, GL_UNSIGNED_SHORT, buffer);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100372 glUseProgram(gr->current_shader->program);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400373 free(buffer);
374}
375
376static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500377repaint_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400378 pixman_region32_t *surf_region)
379{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500380 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400381 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400382 GLfloat *v;
383 unsigned int *vtxcnt;
384 int i, first, nfans;
385
386 /* The final region to be painted is the intersection of
387 * 'region' and 'surf_region'. However, 'region' is in the global
388 * coordinates, and 'surf_region' is in the surface-local
389 * coordinates. texture_region() will iterate over all pairs of
390 * rectangles from both regions, compute the intersection
391 * polygon for each pair, and store it as a triangle fan if
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400392 * it has a non-zero area (at least 3 vertices1, actually).
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400393 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500394 nfans = texture_region(ev, region, surf_region);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400395
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400396 v = gr->vertices.data;
397 vtxcnt = gr->vtxcnt.data;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400398
399 /* position: */
400 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
401 glEnableVertexAttribArray(0);
402
403 /* texcoord: */
404 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
405 glEnableVertexAttribArray(1);
406
407 for (i = 0, first = 0; i < nfans; i++) {
408 glDrawArrays(GL_TRIANGLE_FAN, first, vtxcnt[i]);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400409 if (gr->fan_debug)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500410 triangle_fan_debug(ev, first, vtxcnt[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400411 first += vtxcnt[i];
412 }
413
414 glDisableVertexAttribArray(1);
415 glDisableVertexAttribArray(0);
416
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400417 gr->vertices.size = 0;
418 gr->vtxcnt.size = 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400419}
420
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100421static int
422use_output(struct weston_output *output)
423{
424 static int errored;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100425 struct gl_output_state *go = get_output_state(output);
426 struct gl_renderer *gr = get_renderer(output->compositor);
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100427 EGLBoolean ret;
428
429 ret = eglMakeCurrent(gr->egl_display, go->egl_surface,
430 go->egl_surface, gr->egl_context);
431
432 if (ret == EGL_FALSE) {
433 if (errored)
434 return -1;
435 errored = 1;
436 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +0200437 gl_renderer_print_egl_error_state();
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100438 return -1;
439 }
440
441 return 0;
442}
443
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300444static int
445shader_init(struct gl_shader *shader, struct gl_renderer *gr,
446 const char *vertex_source, const char *fragment_source);
447
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400448static void
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300449use_shader(struct gl_renderer *gr, struct gl_shader *shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400450{
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300451 if (!shader->program) {
452 int ret;
453
454 ret = shader_init(shader, gr,
455 shader->vertex_source,
456 shader->fragment_source);
457
458 if (ret < 0)
459 weston_log("warning: failed to compile shader\n");
460 }
461
John Kåre Alsaker40684142012-11-13 19:10:25 +0100462 if (gr->current_shader == shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400463 return;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400464 glUseProgram(shader->program);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100465 gr->current_shader = shader;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400466}
467
468static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100469shader_uniforms(struct gl_shader *shader,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500470 struct weston_view *view,
471 struct weston_output *output)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400472{
473 int i;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500474 struct gl_surface_state *gs = get_surface_state(view->surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400475
476 glUniformMatrix4fv(shader->proj_uniform,
477 1, GL_FALSE, output->matrix.d);
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100478 glUniform4fv(shader->color_uniform, 1, gs->color);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500479 glUniform1f(shader->alpha_uniform, view->alpha);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400480
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100481 for (i = 0; i < gs->num_textures; i++)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400482 glUniform1i(shader->tex_uniforms[i], i);
483}
484
485static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500486draw_view(struct weston_view *ev, struct weston_output *output,
487 pixman_region32_t *damage) /* in global coordinates */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400488{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500489 struct weston_compositor *ec = ev->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100490 struct gl_renderer *gr = get_renderer(ec);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500491 struct gl_surface_state *gs = get_surface_state(ev->surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400492 /* repaint bounding region in global coordinates: */
493 pixman_region32_t repaint;
494 /* non-opaque region in surface coordinates: */
495 pixman_region32_t surface_blend;
496 GLint filter;
497 int i;
498
499 pixman_region32_init(&repaint);
500 pixman_region32_intersect(&repaint,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500501 &ev->transform.boundingbox, damage);
502 pixman_region32_subtract(&repaint, &repaint, &ev->clip);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400503
504 if (!pixman_region32_not_empty(&repaint))
505 goto out;
506
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400507 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
508
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400509 if (gr->fan_debug) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100510 use_shader(gr, &gr->solid_shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500511 shader_uniforms(&gr->solid_shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400512 }
513
John Kåre Alsaker40684142012-11-13 19:10:25 +0100514 use_shader(gr, gs->shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500515 shader_uniforms(gs->shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400516
Jason Ekstranda7af7042013-10-12 22:38:11 -0500517 if (ev->transform.enabled || output->zoom.active ||
518 output->current_scale != ev->surface->buffer_scale)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400519 filter = GL_LINEAR;
520 else
521 filter = GL_NEAREST;
522
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100523 for (i = 0; i < gs->num_textures; i++) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400524 glActiveTexture(GL_TEXTURE0 + i);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100525 glBindTexture(gs->target, gs->textures[i]);
526 glTexParameteri(gs->target, GL_TEXTURE_MIN_FILTER, filter);
527 glTexParameteri(gs->target, GL_TEXTURE_MAG_FILTER, filter);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400528 }
529
530 /* blended region is whole surface minus opaque region: */
531 pixman_region32_init_rect(&surface_blend, 0, 0,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500532 ev->geometry.width, ev->geometry.height);
533 pixman_region32_subtract(&surface_blend, &surface_blend, &ev->surface->opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400534
Jason Ekstranda7af7042013-10-12 22:38:11 -0500535 /* XXX: Should we be using ev->transform.opaque here? */
536 if (pixman_region32_not_empty(&ev->surface->opaque)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100537 if (gs->shader == &gr->texture_shader_rgba) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400538 /* Special case for RGBA textures with possibly
539 * bad data in alpha channel: use the shader
540 * that forces texture alpha = 1.0.
541 * Xwayland surfaces need this.
542 */
John Kåre Alsaker40684142012-11-13 19:10:25 +0100543 use_shader(gr, &gr->texture_shader_rgbx);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500544 shader_uniforms(&gr->texture_shader_rgbx, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400545 }
546
Jason Ekstranda7af7042013-10-12 22:38:11 -0500547 if (ev->alpha < 1.0)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400548 glEnable(GL_BLEND);
549 else
550 glDisable(GL_BLEND);
551
Jason Ekstranda7af7042013-10-12 22:38:11 -0500552 repaint_region(ev, &repaint, &ev->surface->opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400553 }
554
555 if (pixman_region32_not_empty(&surface_blend)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100556 use_shader(gr, gs->shader);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400557 glEnable(GL_BLEND);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500558 repaint_region(ev, &repaint, &surface_blend);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400559 }
560
561 pixman_region32_fini(&surface_blend);
562
563out:
564 pixman_region32_fini(&repaint);
565}
566
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400567static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500568repaint_views(struct weston_output *output, pixman_region32_t *damage)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400569{
570 struct weston_compositor *compositor = output->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500571 struct weston_view *view;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400572
Jason Ekstranda7af7042013-10-12 22:38:11 -0500573 wl_list_for_each_reverse(view, &compositor->view_list, link)
574 if (view->plane == &compositor->primary_plane)
575 draw_view(view, output, damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400576}
577
John Kåre Alsaker44154502012-11-13 19:10:20 +0100578
579static int
580texture_border(struct weston_output *output)
581{
582 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100583 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100584 GLfloat *d;
Kristian Høgsberg73db9242013-08-28 23:05:29 -0700585 unsigned short *p;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100586 int i, j, k, n;
587 GLfloat x[4], y[4], u[4], v[4];
588
589 x[0] = -gr->border.left;
590 x[1] = 0;
Hardeningff39efa2013-09-18 23:56:35 +0200591 x[2] = output->current_mode->width;
592 x[3] = output->current_mode->width + gr->border.right;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100593
594 y[0] = -gr->border.top;
595 y[1] = 0;
Hardeningff39efa2013-09-18 23:56:35 +0200596 y[2] = output->current_mode->height;
597 y[3] = output->current_mode->height + gr->border.bottom;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100598
599 u[0] = 0.0;
600 u[1] = (GLfloat) gr->border.left / gr->border.width;
601 u[2] = (GLfloat) (gr->border.width - gr->border.right) / gr->border.width;
602 u[3] = 1.0;
603
604 v[0] = 0.0;
605 v[1] = (GLfloat) gr->border.top / gr->border.height;
606 v[2] = (GLfloat) (gr->border.height - gr->border.bottom) / gr->border.height;
607 v[3] = 1.0;
608
609 n = 8;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400610 d = wl_array_add(&gr->vertices, n * 16 * sizeof *d);
611 p = wl_array_add(&gr->indices, n * 6 * sizeof *p);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100612
613 k = 0;
614 for (i = 0; i < 3; i++)
615 for (j = 0; j < 3; j++) {
616
617 if (i == 1 && j == 1)
618 continue;
619
620 d[ 0] = x[i];
621 d[ 1] = y[j];
622 d[ 2] = u[i];
623 d[ 3] = v[j];
624
625 d[ 4] = x[i];
626 d[ 5] = y[j + 1];
627 d[ 6] = u[i];
628 d[ 7] = v[j + 1];
629
630 d[ 8] = x[i + 1];
631 d[ 9] = y[j];
632 d[10] = u[i + 1];
633 d[11] = v[j];
634
635 d[12] = x[i + 1];
636 d[13] = y[j + 1];
637 d[14] = u[i + 1];
638 d[15] = v[j + 1];
639
640 p[0] = k + 0;
641 p[1] = k + 1;
642 p[2] = k + 2;
643 p[3] = k + 2;
644 p[4] = k + 1;
645 p[5] = k + 3;
646
647 d += 16;
648 p += 6;
649 k += 4;
650 }
651
652 return k / 4;
653}
654
655static void
656draw_border(struct weston_output *output)
657{
658 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100659 struct gl_renderer *gr = get_renderer(ec);
660 struct gl_shader *shader = &gr->texture_shader_rgba;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100661 GLfloat *v;
662 int n;
663
664 glDisable(GL_BLEND);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100665 use_shader(gr, shader);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100666
667 glUniformMatrix4fv(shader->proj_uniform,
668 1, GL_FALSE, output->matrix.d);
669
670 glUniform1i(shader->tex_uniforms[0], 0);
671 glUniform1f(shader->alpha_uniform, 1);
672
673 n = texture_border(output);
674
675 glActiveTexture(GL_TEXTURE0);
676 glBindTexture(GL_TEXTURE_2D, gr->border.texture);
677
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400678 v = gr->vertices.data;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100679 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
680 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
681 glEnableVertexAttribArray(0);
682 glEnableVertexAttribArray(1);
683
684 glDrawElements(GL_TRIANGLES, n * 6,
Kristian Høgsberg73db9242013-08-28 23:05:29 -0700685 GL_UNSIGNED_SHORT, gr->indices.data);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100686
687 glDisableVertexAttribArray(1);
688 glDisableVertexAttribArray(0);
689
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400690 gr->vertices.size = 0;
691 gr->indices.size = 0;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100692}
693
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400694static void
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200695output_get_buffer_damage(struct weston_output *output,
696 pixman_region32_t *buffer_damage)
697{
698 struct gl_output_state *go = get_output_state(output);
699 struct gl_renderer *gr = get_renderer(output->compositor);
700 EGLint buffer_age = 0;
701 EGLBoolean ret;
702 int i;
703
704 if (gr->has_egl_buffer_age) {
705 ret = eglQuerySurface(gr->egl_display, go->egl_surface,
706 EGL_BUFFER_AGE_EXT, &buffer_age);
707 if (ret == EGL_FALSE) {
708 weston_log("buffer age query failed.\n");
709 gl_renderer_print_egl_error_state();
710 }
711 }
712
713 if (buffer_age == 0 || buffer_age - 1 > BUFFER_DAMAGE_COUNT)
714 pixman_region32_copy(buffer_damage, &output->region);
715 else
716 for (i = 0; i < buffer_age - 1; i++)
717 pixman_region32_union(buffer_damage, buffer_damage,
718 &go->buffer_damage[i]);
719}
720
721static void
722output_rotate_damage(struct weston_output *output,
723 pixman_region32_t *output_damage)
724{
725 struct gl_output_state *go = get_output_state(output);
726 struct gl_renderer *gr = get_renderer(output->compositor);
727 int i;
728
729 if (!gr->has_egl_buffer_age)
730 return;
731
732 for (i = BUFFER_DAMAGE_COUNT - 1; i >= 1; i--)
733 pixman_region32_copy(&go->buffer_damage[i],
734 &go->buffer_damage[i - 1]);
735
736 pixman_region32_copy(&go->buffer_damage[0], output_damage);
737}
738
739static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100740gl_renderer_repaint_output(struct weston_output *output,
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400741 pixman_region32_t *output_damage)
742{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100743 struct gl_output_state *go = get_output_state(output);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400744 struct weston_compositor *compositor = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100745 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400746 EGLBoolean ret;
747 static int errored;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200748 int32_t width, height;
749 pixman_region32_t buffer_damage, total_damage;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400750
Hardeningff39efa2013-09-18 23:56:35 +0200751 width = output->current_mode->width +
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400752 output->border.left + output->border.right;
Hardeningff39efa2013-09-18 23:56:35 +0200753 height = output->current_mode->height +
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400754 output->border.top + output->border.bottom;
755
756 glViewport(0, 0, width, height);
757
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100758 if (use_output(output) < 0)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400759 return;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400760
761 /* if debugging, redraw everything outside the damage to clean up
762 * debug lines from the previous draw on this buffer:
763 */
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400764 if (gr->fan_debug) {
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400765 pixman_region32_t undamaged;
766 pixman_region32_init(&undamaged);
767 pixman_region32_subtract(&undamaged, &output->region,
768 output_damage);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400769 gr->fan_debug = 0;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500770 repaint_views(output, &undamaged);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400771 gr->fan_debug = 1;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400772 pixman_region32_fini(&undamaged);
773 }
774
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +0200775 pixman_region32_init(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200776 pixman_region32_init(&buffer_damage);
777
778 output_get_buffer_damage(output, &buffer_damage);
779 output_rotate_damage(output, output_damage);
780
781 pixman_region32_union(&total_damage, &buffer_damage, output_damage);
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300782
Jason Ekstranda7af7042013-10-12 22:38:11 -0500783 repaint_views(output, &total_damage);
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +0200784
785 pixman_region32_fini(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200786 pixman_region32_fini(&buffer_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400787
John Kåre Alsaker44154502012-11-13 19:10:20 +0100788 if (gr->border.texture)
789 draw_border(output);
790
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +0200791 pixman_region32_copy(&output->previous_damage, output_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400792 wl_signal_emit(&output->frame_signal, output);
793
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100794 ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400795 if (ret == EGL_FALSE && !errored) {
796 errored = 1;
797 weston_log("Failed in eglSwapBuffers.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +0200798 gl_renderer_print_egl_error_state();
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400799 }
800
801}
Kristian Høgsberg25894fc2012-09-05 22:06:26 -0400802
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100803static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100804gl_renderer_read_pixels(struct weston_output *output,
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100805 pixman_format_code_t format, void *pixels,
806 uint32_t x, uint32_t y,
807 uint32_t width, uint32_t height)
808{
809 GLenum gl_format;
810
811 switch (format) {
812 case PIXMAN_a8r8g8b8:
813 gl_format = GL_BGRA_EXT;
814 break;
815 case PIXMAN_a8b8g8r8:
816 gl_format = GL_RGBA;
817 break;
818 default:
819 return -1;
820 }
821
822 if (use_output(output) < 0)
823 return -1;
824
825 glPixelStorei(GL_PACK_ALIGNMENT, 1);
826 glReadPixels(x, y, width, height, gl_format,
827 GL_UNSIGNED_BYTE, pixels);
828
829 return 0;
830}
831
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400832static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100833gl_renderer_flush_damage(struct weston_surface *surface)
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400834{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100835 struct gl_renderer *gr = get_renderer(surface->compositor);
836 struct gl_surface_state *gs = get_surface_state(surface);
Jason Ekstrand6bd62942013-06-20 20:38:23 -0500837 struct weston_buffer *buffer = gs->buffer_ref.buffer;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500838 struct weston_view *view;
839 int texture_used;
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200840 GLenum format;
841 int pixel_type;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100842
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700843#ifdef GL_EXT_unpack_subimage
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400844 pixman_box32_t *rectangles;
845 void *data;
846 int i, n;
847#endif
848
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200849 pixman_region32_union(&gs->texture_damage,
850 &gs->texture_damage, &surface->damage);
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200851
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200852 if (!buffer)
853 return;
854
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200855 /* Avoid upload, if the texture won't be used this time.
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200856 * We still accumulate the damage in texture_damage, and
857 * hold the reference to the buffer, in case the surface
858 * migrates back to the primary plane.
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200859 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500860 texture_used = 0;
861 wl_list_for_each(view, &surface->views, surface_link) {
862 if (view->plane == &surface->compositor->primary_plane) {
863 texture_used = 1;
864 break;
865 }
866 }
867 if (!texture_used)
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200868 return;
869
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200870 if (!pixman_region32_not_empty(&gs->texture_damage))
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200871 goto done;
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200872
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200873 switch (wl_shm_buffer_get_format(buffer->shm_buffer)) {
874 case WL_SHM_FORMAT_XRGB8888:
875 case WL_SHM_FORMAT_ARGB8888:
876 format = GL_BGRA_EXT;
877 pixel_type = GL_UNSIGNED_BYTE;
878 break;
879 case WL_SHM_FORMAT_RGB565:
880 format = GL_RGB;
881 pixel_type = GL_UNSIGNED_SHORT_5_6_5;
882 break;
883 default:
884 weston_log("warning: unknown shm buffer format\n");
885 format = GL_BGRA_EXT;
886 pixel_type = GL_UNSIGNED_BYTE;
887 }
888
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100889 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400890
John Kåre Alsaker320711d2012-11-13 19:10:27 +0100891 if (!gr->has_unpack_subimage) {
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200892 glTexImage2D(GL_TEXTURE_2D, 0, format,
Pekka Paalanen68033ac2012-12-04 15:58:15 +0200893 gs->pitch, buffer->height, 0,
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200894 format, pixel_type,
Jason Ekstrand6bd62942013-06-20 20:38:23 -0500895 wl_shm_buffer_get_data(buffer->shm_buffer));
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400896
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200897 goto done;
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400898 }
899
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700900#ifdef GL_EXT_unpack_subimage
901 glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, gs->pitch);
Jason Ekstrand6bd62942013-06-20 20:38:23 -0500902 data = wl_shm_buffer_get_data(buffer->shm_buffer);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300903
904 if (gs->needs_full_upload) {
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700905 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
906 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300907 glTexSubImage2D(GL_TEXTURE_2D, 0,
908 0, 0, gs->pitch, buffer->height,
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200909 format, pixel_type, data);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300910 goto done;
911 }
912
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200913 rectangles = pixman_region32_rectangles(&gs->texture_damage, &n);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400914 for (i = 0; i < n; i++) {
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200915 pixman_box32_t r;
916
917 r = weston_surface_to_buffer_rect(surface, rectangles[i]);
918
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700919 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, r.x1);
920 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, r.y1);
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200921 glTexSubImage2D(GL_TEXTURE_2D, 0, r.x1, r.y1,
922 r.x2 - r.x1, r.y2 - r.y1,
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200923 format, pixel_type, data);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400924 }
925#endif
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200926
927done:
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200928 pixman_region32_fini(&gs->texture_damage);
929 pixman_region32_init(&gs->texture_damage);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300930 gs->needs_full_upload = 0;
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200931
932 weston_buffer_reference(&gs->buffer_ref, NULL);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400933}
934
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400935static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100936ensure_textures(struct gl_surface_state *gs, int num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400937{
938 int i;
939
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100940 if (num_textures <= gs->num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400941 return;
942
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100943 for (i = gs->num_textures; i < num_textures; i++) {
944 glGenTextures(1, &gs->textures[i]);
945 glBindTexture(gs->target, gs->textures[i]);
946 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400947 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100948 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400949 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
950 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100951 gs->num_textures = num_textures;
952 glBindTexture(gs->target, 0);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400953}
954
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400955static void
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +0300956gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
957 struct wl_shm_buffer *shm_buffer)
958{
959 struct weston_compositor *ec = es->compositor;
960 struct gl_renderer *gr = get_renderer(ec);
961 struct gl_surface_state *gs = get_surface_state(es);
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200962 int pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +0300963
964 buffer->shm_buffer = shm_buffer;
965 buffer->width = wl_shm_buffer_get_width(shm_buffer);
966 buffer->height = wl_shm_buffer_get_height(shm_buffer);
967
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200968 switch (wl_shm_buffer_get_format(shm_buffer)) {
969 case WL_SHM_FORMAT_XRGB8888:
970 gs->shader = &gr->texture_shader_rgbx;
971 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
972 break;
973 case WL_SHM_FORMAT_ARGB8888:
974 gs->shader = &gr->texture_shader_rgba;
975 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
976 break;
977 case WL_SHM_FORMAT_RGB565:
978 gs->shader = &gr->texture_shader_rgbx;
979 pitch = wl_shm_buffer_get_stride(shm_buffer) / 2;
980 break;
981 default:
982 weston_log("warning: unknown shm buffer format\n");
983 gs->shader = &gr->texture_shader_rgba;
984 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
985 }
986
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +0300987 /* Only allocate a texture if it doesn't match existing one.
988 * If a switch from DRM allocated buffer to a SHM buffer is
989 * happening, we need to allocate a new texture buffer. */
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200990 if (pitch != gs->pitch ||
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +0300991 buffer->height != gs->height ||
992 gs->buffer_type != BUFFER_TYPE_SHM) {
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200993 gs->pitch = pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +0300994 gs->height = buffer->height;
995 gs->target = GL_TEXTURE_2D;
996 gs->buffer_type = BUFFER_TYPE_SHM;
997 gs->needs_full_upload = 1;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +0400998 gs->y_inverted = 1;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +0300999
1000 ensure_textures(gs, 1);
1001 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
1002 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1003 gs->pitch, buffer->height, 0,
1004 GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
1005 }
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001006}
1007
1008static void
1009gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
1010 uint32_t format)
1011{
1012 struct weston_compositor *ec = es->compositor;
1013 struct gl_renderer *gr = get_renderer(ec);
1014 struct gl_surface_state *gs = get_surface_state(es);
1015 EGLint attribs[3];
1016 int i, num_planes;
1017
1018 buffer->legacy_buffer = (struct wl_buffer *)buffer->resource;
1019 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1020 EGL_WIDTH, &buffer->width);
1021 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1022 EGL_HEIGHT, &buffer->height);
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001023 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1024 EGL_WAYLAND_Y_INVERTED_WL, &buffer->y_inverted);
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001025
1026 for (i = 0; i < gs->num_images; i++)
1027 gr->destroy_image(gr->egl_display, gs->images[i]);
1028 gs->num_images = 0;
1029 gs->target = GL_TEXTURE_2D;
1030 switch (format) {
1031 case EGL_TEXTURE_RGB:
1032 case EGL_TEXTURE_RGBA:
1033 default:
1034 num_planes = 1;
1035 gs->shader = &gr->texture_shader_rgba;
1036 break;
1037 case EGL_TEXTURE_EXTERNAL_WL:
1038 num_planes = 1;
1039 gs->target = GL_TEXTURE_EXTERNAL_OES;
1040 gs->shader = &gr->texture_shader_egl_external;
1041 break;
1042 case EGL_TEXTURE_Y_UV_WL:
1043 num_planes = 2;
1044 gs->shader = &gr->texture_shader_y_uv;
1045 break;
1046 case EGL_TEXTURE_Y_U_V_WL:
1047 num_planes = 3;
1048 gs->shader = &gr->texture_shader_y_u_v;
1049 break;
1050 case EGL_TEXTURE_Y_XUXV_WL:
1051 num_planes = 2;
1052 gs->shader = &gr->texture_shader_y_xuxv;
1053 break;
1054 }
1055
1056 ensure_textures(gs, num_planes);
1057 for (i = 0; i < num_planes; i++) {
1058 attribs[0] = EGL_WAYLAND_PLANE_WL;
1059 attribs[1] = i;
1060 attribs[2] = EGL_NONE;
1061 gs->images[i] = gr->create_image(gr->egl_display,
1062 NULL,
1063 EGL_WAYLAND_BUFFER_WL,
1064 buffer->legacy_buffer,
1065 attribs);
1066 if (!gs->images[i]) {
1067 weston_log("failed to create img for plane %d\n", i);
1068 continue;
1069 }
1070 gs->num_images++;
1071
1072 glActiveTexture(GL_TEXTURE0 + i);
1073 glBindTexture(gs->target, gs->textures[i]);
1074 gr->image_target_texture_2d(gs->target,
1075 gs->images[i]);
1076 }
1077
1078 gs->pitch = buffer->width;
1079 gs->height = buffer->height;
1080 gs->buffer_type = BUFFER_TYPE_EGL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001081 gs->y_inverted = buffer->y_inverted;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001082}
1083
1084static void
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001085gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001086{
1087 struct weston_compositor *ec = es->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001088 struct gl_renderer *gr = get_renderer(ec);
1089 struct gl_surface_state *gs = get_surface_state(es);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001090 struct wl_shm_buffer *shm_buffer;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001091 EGLint format;
1092 int i;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001093
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001094 weston_buffer_reference(&gs->buffer_ref, buffer);
1095
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001096 if (!buffer) {
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001097 for (i = 0; i < gs->num_images; i++) {
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001098 gr->destroy_image(gr->egl_display, gs->images[i]);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001099 gs->images[i] = NULL;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001100 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001101 gs->num_images = 0;
1102 glDeleteTextures(gs->num_textures, gs->textures);
1103 gs->num_textures = 0;
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001104 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001105 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001106 return;
1107 }
1108
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001109 shm_buffer = wl_shm_buffer_get(buffer->resource);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001110
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001111 if (shm_buffer)
1112 gl_renderer_attach_shm(es, buffer, shm_buffer);
Kristian Høgsberg47229392013-08-07 11:59:54 -07001113 else if (gr->query_buffer(gr->egl_display, (void *) buffer->resource,
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001114 EGL_TEXTURE_FORMAT, &format))
1115 gl_renderer_attach_egl(es, buffer, format);
1116 else {
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001117 weston_log("unhandled buffer type!\n");
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001118 weston_buffer_reference(&gs->buffer_ref, NULL);
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001119 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001120 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001121 }
1122}
1123
Kristian Høgsberg42263852012-09-06 21:59:29 -04001124static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001125gl_renderer_surface_set_color(struct weston_surface *surface,
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001126 float red, float green, float blue, float alpha)
1127{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001128 struct gl_surface_state *gs = get_surface_state(surface);
1129 struct gl_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001130
1131 gs->color[0] = red;
1132 gs->color[1] = green;
1133 gs->color[2] = blue;
1134 gs->color[3] = alpha;
1135
John Kåre Alsaker40684142012-11-13 19:10:25 +01001136 gs->shader = &gr->solid_shader;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001137}
1138
1139static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001140gl_renderer_create_surface(struct weston_surface *surface)
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001141{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001142 struct gl_surface_state *gs;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001143
1144 gs = calloc(1, sizeof *gs);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001145 if (!gs)
1146 return -1;
1147
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001148 /* A buffer is never attached to solid color surfaces, yet
1149 * they still go through texcoord computations. Do not divide
1150 * by zero there.
1151 */
1152 gs->pitch = 1;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001153 gs->y_inverted = 1;
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001154
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001155 pixman_region32_init(&gs->texture_damage);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001156 surface->renderer_state = gs;
1157
1158 return 0;
1159}
1160
1161static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001162gl_renderer_destroy_surface(struct weston_surface *surface)
Kristian Høgsberg42263852012-09-06 21:59:29 -04001163{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001164 struct gl_surface_state *gs = get_surface_state(surface);
1165 struct gl_renderer *gr = get_renderer(surface->compositor);
Kristian Høgsberg42263852012-09-06 21:59:29 -04001166 int i;
1167
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001168 glDeleteTextures(gs->num_textures, gs->textures);
Kristian Høgsberg42263852012-09-06 21:59:29 -04001169
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001170 for (i = 0; i < gs->num_images; i++)
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001171 gr->destroy_image(gr->egl_display, gs->images[i]);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001172
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001173 weston_buffer_reference(&gs->buffer_ref, NULL);
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001174 pixman_region32_fini(&gs->texture_damage);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001175 free(gs);
Kristian Høgsberg42263852012-09-06 21:59:29 -04001176}
1177
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001178static const char vertex_shader[] =
1179 "uniform mat4 proj;\n"
1180 "attribute vec2 position;\n"
1181 "attribute vec2 texcoord;\n"
1182 "varying vec2 v_texcoord;\n"
1183 "void main()\n"
1184 "{\n"
1185 " gl_Position = proj * vec4(position, 0.0, 1.0);\n"
1186 " v_texcoord = texcoord;\n"
1187 "}\n";
1188
1189/* Declare common fragment shader uniforms */
1190#define FRAGMENT_CONVERT_YUV \
1191 " y *= alpha;\n" \
1192 " u *= alpha;\n" \
1193 " v *= alpha;\n" \
1194 " gl_FragColor.r = y + 1.59602678 * v;\n" \
1195 " gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n" \
1196 " gl_FragColor.b = y + 2.01723214 * u;\n" \
1197 " gl_FragColor.a = alpha;\n"
1198
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001199static const char fragment_debug[] =
1200 " gl_FragColor = vec4(0.0, 0.3, 0.0, 0.2) + gl_FragColor * 0.8;\n";
1201
1202static const char fragment_brace[] =
1203 "}\n";
1204
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001205static const char texture_fragment_shader_rgba[] =
1206 "precision mediump float;\n"
1207 "varying vec2 v_texcoord;\n"
1208 "uniform sampler2D tex;\n"
1209 "uniform float alpha;\n"
1210 "void main()\n"
1211 "{\n"
1212 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001213 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001214
1215static const char texture_fragment_shader_rgbx[] =
1216 "precision mediump float;\n"
1217 "varying vec2 v_texcoord;\n"
1218 "uniform sampler2D tex;\n"
1219 "uniform float alpha;\n"
1220 "void main()\n"
1221 "{\n"
1222 " gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb\n;"
1223 " gl_FragColor.a = alpha;\n"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001224 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001225
1226static const char texture_fragment_shader_egl_external[] =
1227 "#extension GL_OES_EGL_image_external : require\n"
1228 "precision mediump float;\n"
1229 "varying vec2 v_texcoord;\n"
1230 "uniform samplerExternalOES tex;\n"
1231 "uniform float alpha;\n"
1232 "void main()\n"
1233 "{\n"
1234 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001235 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001236
1237static const char texture_fragment_shader_y_uv[] =
1238 "precision mediump float;\n"
1239 "uniform sampler2D tex;\n"
1240 "uniform sampler2D tex1;\n"
1241 "varying vec2 v_texcoord;\n"
1242 "uniform float alpha;\n"
1243 "void main() {\n"
1244 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1245 " float u = texture2D(tex1, v_texcoord).r - 0.5;\n"
1246 " float v = texture2D(tex1, v_texcoord).g - 0.5;\n"
1247 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001248 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001249
1250static const char texture_fragment_shader_y_u_v[] =
1251 "precision mediump float;\n"
1252 "uniform sampler2D tex;\n"
1253 "uniform sampler2D tex1;\n"
1254 "uniform sampler2D tex2;\n"
1255 "varying vec2 v_texcoord;\n"
1256 "uniform float alpha;\n"
1257 "void main() {\n"
1258 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1259 " float u = texture2D(tex1, v_texcoord).x - 0.5;\n"
1260 " float v = texture2D(tex2, v_texcoord).x - 0.5;\n"
1261 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001262 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001263
1264static const char texture_fragment_shader_y_xuxv[] =
1265 "precision mediump float;\n"
1266 "uniform sampler2D tex;\n"
1267 "uniform sampler2D tex1;\n"
1268 "varying vec2 v_texcoord;\n"
1269 "uniform float alpha;\n"
1270 "void main() {\n"
1271 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1272 " float u = texture2D(tex1, v_texcoord).g - 0.5;\n"
1273 " float v = texture2D(tex1, v_texcoord).a - 0.5;\n"
1274 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001275 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001276
1277static const char solid_fragment_shader[] =
1278 "precision mediump float;\n"
1279 "uniform vec4 color;\n"
1280 "uniform float alpha;\n"
1281 "void main()\n"
1282 "{\n"
1283 " gl_FragColor = alpha * color\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001284 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001285
1286static int
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001287compile_shader(GLenum type, int count, const char **sources)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001288{
1289 GLuint s;
1290 char msg[512];
1291 GLint status;
1292
1293 s = glCreateShader(type);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001294 glShaderSource(s, count, sources, NULL);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001295 glCompileShader(s);
1296 glGetShaderiv(s, GL_COMPILE_STATUS, &status);
1297 if (!status) {
1298 glGetShaderInfoLog(s, sizeof msg, NULL, msg);
1299 weston_log("shader info: %s\n", msg);
1300 return GL_NONE;
1301 }
1302
1303 return s;
1304}
1305
1306static int
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03001307shader_init(struct gl_shader *shader, struct gl_renderer *renderer,
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001308 const char *vertex_source, const char *fragment_source)
1309{
1310 char msg[512];
1311 GLint status;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001312 int count;
1313 const char *sources[3];
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001314
1315 shader->vertex_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001316 compile_shader(GL_VERTEX_SHADER, 1, &vertex_source);
1317
1318 if (renderer->fragment_shader_debug) {
1319 sources[0] = fragment_source;
1320 sources[1] = fragment_debug;
1321 sources[2] = fragment_brace;
1322 count = 3;
1323 } else {
1324 sources[0] = fragment_source;
1325 sources[1] = fragment_brace;
1326 count = 2;
1327 }
1328
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001329 shader->fragment_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001330 compile_shader(GL_FRAGMENT_SHADER, count, sources);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001331
1332 shader->program = glCreateProgram();
1333 glAttachShader(shader->program, shader->vertex_shader);
1334 glAttachShader(shader->program, shader->fragment_shader);
1335 glBindAttribLocation(shader->program, 0, "position");
1336 glBindAttribLocation(shader->program, 1, "texcoord");
1337
1338 glLinkProgram(shader->program);
1339 glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
1340 if (!status) {
1341 glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
1342 weston_log("link info: %s\n", msg);
1343 return -1;
1344 }
1345
1346 shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
1347 shader->tex_uniforms[0] = glGetUniformLocation(shader->program, "tex");
1348 shader->tex_uniforms[1] = glGetUniformLocation(shader->program, "tex1");
1349 shader->tex_uniforms[2] = glGetUniformLocation(shader->program, "tex2");
1350 shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
1351 shader->color_uniform = glGetUniformLocation(shader->program, "color");
1352
1353 return 0;
1354}
1355
1356static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001357shader_release(struct gl_shader *shader)
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001358{
1359 glDeleteShader(shader->vertex_shader);
1360 glDeleteShader(shader->fragment_shader);
1361 glDeleteProgram(shader->program);
1362
1363 shader->vertex_shader = 0;
1364 shader->fragment_shader = 0;
1365 shader->program = 0;
1366}
1367
1368static void
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001369log_extensions(const char *name, const char *extensions)
1370{
1371 const char *p, *end;
1372 int l;
1373 int len;
1374
1375 l = weston_log("%s:", name);
1376 p = extensions;
1377 while (*p) {
1378 end = strchrnul(p, ' ');
1379 len = end - p;
1380 if (l + len > 78)
1381 l = weston_log_continue("\n" STAMP_SPACE "%.*s",
1382 len, p);
1383 else
1384 l += weston_log_continue(" %.*s", len, p);
1385 for (p = end; isspace(*p); p++)
1386 ;
1387 }
1388 weston_log_continue("\n");
1389}
1390
1391static void
1392log_egl_gl_info(EGLDisplay egldpy)
1393{
1394 const char *str;
1395
1396 str = eglQueryString(egldpy, EGL_VERSION);
1397 weston_log("EGL version: %s\n", str ? str : "(null)");
1398
1399 str = eglQueryString(egldpy, EGL_VENDOR);
1400 weston_log("EGL vendor: %s\n", str ? str : "(null)");
1401
1402 str = eglQueryString(egldpy, EGL_CLIENT_APIS);
1403 weston_log("EGL client APIs: %s\n", str ? str : "(null)");
1404
1405 str = eglQueryString(egldpy, EGL_EXTENSIONS);
1406 log_extensions("EGL extensions", str ? str : "(null)");
1407
1408 str = (char *)glGetString(GL_VERSION);
1409 weston_log("GL version: %s\n", str ? str : "(null)");
1410
1411 str = (char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
1412 weston_log("GLSL version: %s\n", str ? str : "(null)");
1413
1414 str = (char *)glGetString(GL_VENDOR);
1415 weston_log("GL vendor: %s\n", str ? str : "(null)");
1416
1417 str = (char *)glGetString(GL_RENDERER);
1418 weston_log("GL renderer: %s\n", str ? str : "(null)");
1419
1420 str = (char *)glGetString(GL_EXTENSIONS);
1421 log_extensions("GL extensions", str ? str : "(null)");
1422}
1423
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001424static void
1425log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
1426{
1427 EGLint r, g, b, a;
1428
1429 weston_log("Chosen EGL config details:\n");
1430
1431 weston_log_continue(STAMP_SPACE "RGBA bits");
1432 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_RED_SIZE, &r) &&
1433 eglGetConfigAttrib(egldpy, eglconfig, EGL_GREEN_SIZE, &g) &&
1434 eglGetConfigAttrib(egldpy, eglconfig, EGL_BLUE_SIZE, &b) &&
1435 eglGetConfigAttrib(egldpy, eglconfig, EGL_ALPHA_SIZE, &a))
1436 weston_log_continue(": %d %d %d %d\n", r, g, b, a);
1437 else
1438 weston_log_continue(" unknown\n");
1439
1440 weston_log_continue(STAMP_SPACE "swap interval range");
1441 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_MIN_SWAP_INTERVAL, &a) &&
1442 eglGetConfigAttrib(egldpy, eglconfig, EGL_MAX_SWAP_INTERVAL, &b))
1443 weston_log_continue(": %d - %d\n", a, b);
1444 else
1445 weston_log_continue(" unknown\n");
1446}
1447
John Kåre Alsaker44154502012-11-13 19:10:20 +01001448static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001449output_apply_border(struct weston_output *output, struct gl_renderer *gr)
John Kåre Alsaker44154502012-11-13 19:10:20 +01001450{
1451 output->border.top = gr->border.top;
1452 output->border.bottom = gr->border.bottom;
1453 output->border.left = gr->border.left;
1454 output->border.right = gr->border.right;
1455}
1456
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001457static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001458gl_renderer_set_border(struct weston_compositor *ec, int32_t width, int32_t height, void *data,
John Kåre Alsaker44154502012-11-13 19:10:20 +01001459 int32_t *edges)
1460{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001461 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker44154502012-11-13 19:10:20 +01001462 struct weston_output *output;
1463
1464 gr->border.left = edges[0];
1465 gr->border.right = edges[1];
1466 gr->border.top = edges[2];
1467 gr->border.bottom = edges[3];
1468
1469 gr->border.width = width;
1470 gr->border.height = height;
1471
1472 glGenTextures(1, &gr->border.texture);
1473 glBindTexture(GL_TEXTURE_2D, gr->border.texture);
1474 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1475 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1476 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1477 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1478
1479 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1480 width,
1481 height,
1482 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
1483 data);
1484
1485 wl_list_for_each(output, &ec->output_list, link)
1486 output_apply_border(output, gr);
1487}
1488
John Kåre Alsaker94659272012-11-13 19:10:18 +01001489static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001490gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001491
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001492static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001493gl_renderer_output_create(struct weston_output *output,
John Kåre Alsaker94659272012-11-13 19:10:18 +01001494 EGLNativeWindowType window)
1495{
1496 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001497 struct gl_renderer *gr = get_renderer(ec);
1498 struct gl_output_state *go = calloc(1, sizeof *go);
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001499 int i;
John Kåre Alsaker94659272012-11-13 19:10:18 +01001500
1501 if (!go)
1502 return -1;
1503
1504 go->egl_surface =
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001505 eglCreateWindowSurface(gr->egl_display,
1506 gr->egl_config,
John Kåre Alsaker94659272012-11-13 19:10:18 +01001507 window, NULL);
1508
1509 if (go->egl_surface == EGL_NO_SURFACE) {
1510 weston_log("failed to create egl surface\n");
1511 free(go);
1512 return -1;
1513 }
1514
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001515 if (gr->egl_context == NULL)
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001516 if (gl_renderer_setup(ec, go->egl_surface) < 0) {
John Kåre Alsaker94659272012-11-13 19:10:18 +01001517 free(go);
1518 return -1;
1519 }
1520
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001521 for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001522 pixman_region32_init(&go->buffer_damage[i]);
1523
John Kåre Alsaker94659272012-11-13 19:10:18 +01001524 output->renderer_state = go;
1525
John Kåre Alsaker44154502012-11-13 19:10:20 +01001526 output_apply_border(output, gr);
1527
John Kåre Alsaker94659272012-11-13 19:10:18 +01001528 return 0;
1529}
1530
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001531static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001532gl_renderer_output_destroy(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01001533{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001534 struct gl_renderer *gr = get_renderer(output->compositor);
1535 struct gl_output_state *go = get_output_state(output);
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001536 int i;
1537
1538 for (i = 0; i < 2; i++)
1539 pixman_region32_fini(&go->buffer_damage[i]);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001540
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001541 eglDestroySurface(gr->egl_display, go->egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001542
1543 free(go);
1544}
1545
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001546static EGLSurface
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001547gl_renderer_output_surface(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01001548{
1549 return get_output_state(output)->egl_surface;
1550}
1551
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03001552static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001553gl_renderer_destroy(struct weston_compositor *ec)
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001554{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001555 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001556
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001557 if (gr->has_bind_display)
1558 gr->unbind_display(gr->egl_display, ec->wl_display);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001559
1560 /* Work around crash in egl_dri2.c's dri2_make_current() - when does this apply? */
1561 eglMakeCurrent(gr->egl_display,
1562 EGL_NO_SURFACE, EGL_NO_SURFACE,
1563 EGL_NO_CONTEXT);
1564
1565 eglTerminate(gr->egl_display);
1566 eglReleaseThread();
Scott Moreau976a0502013-03-07 10:15:17 -07001567
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -04001568 wl_array_release(&gr->vertices);
1569 wl_array_release(&gr->indices);
1570 wl_array_release(&gr->vtxcnt);
1571
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +03001572 weston_binding_destroy(gr->fragment_binding);
1573 weston_binding_destroy(gr->fan_binding);
1574
Scott Moreau976a0502013-03-07 10:15:17 -07001575 free(gr);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001576}
1577
1578static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001579egl_choose_config(struct gl_renderer *gr, const EGLint *attribs,
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001580 const EGLint *visual_id)
1581{
1582 EGLint count = 0;
1583 EGLint matched = 0;
1584 EGLConfig *configs;
1585 int i;
1586
1587 if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1)
1588 return -1;
1589
1590 configs = calloc(count, sizeof *configs);
1591 if (!configs)
1592 return -1;
1593
1594 if (!eglChooseConfig(gr->egl_display, attribs, configs,
1595 count, &matched))
1596 goto out;
1597
1598 for (i = 0; i < matched; ++i) {
1599 EGLint id;
1600
1601 if (visual_id) {
1602 if (!eglGetConfigAttrib(gr->egl_display,
1603 configs[i], EGL_NATIVE_VISUAL_ID,
1604 &id))
1605 continue;
1606
Kristian Høgsbergc3ea26c2013-09-25 15:46:42 -07001607 if (id != 0 && id != *visual_id)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001608 continue;
1609 }
1610
1611 gr->egl_config = configs[i];
1612
1613 free(configs);
1614 return 0;
1615 }
1616
1617out:
1618 free(configs);
1619 return -1;
1620}
1621
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001622static const EGLint gl_renderer_opaque_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001623 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1624 EGL_RED_SIZE, 1,
1625 EGL_GREEN_SIZE, 1,
1626 EGL_BLUE_SIZE, 1,
1627 EGL_ALPHA_SIZE, 0,
1628 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1629 EGL_NONE
1630};
1631
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001632static const EGLint gl_renderer_alpha_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001633 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1634 EGL_RED_SIZE, 1,
1635 EGL_GREEN_SIZE, 1,
1636 EGL_BLUE_SIZE, 1,
1637 EGL_ALPHA_SIZE, 1,
1638 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1639 EGL_NONE
1640};
1641
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001642static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001643gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001644 const EGLint *attribs, const EGLint *visual_id)
1645{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001646 struct gl_renderer *gr;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001647 EGLint major, minor;
1648
1649 gr = calloc(1, sizeof *gr);
1650
1651 if (gr == NULL)
1652 return -1;
1653
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001654 gr->base.read_pixels = gl_renderer_read_pixels;
1655 gr->base.repaint_output = gl_renderer_repaint_output;
1656 gr->base.flush_damage = gl_renderer_flush_damage;
1657 gr->base.attach = gl_renderer_attach;
1658 gr->base.create_surface = gl_renderer_create_surface;
1659 gr->base.surface_set_color = gl_renderer_surface_set_color;
1660 gr->base.destroy_surface = gl_renderer_destroy_surface;
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03001661 gr->base.destroy = gl_renderer_destroy;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001662
1663 gr->egl_display = eglGetDisplay(display);
1664 if (gr->egl_display == EGL_NO_DISPLAY) {
1665 weston_log("failed to create display\n");
1666 goto err_egl;
1667 }
1668
1669 if (!eglInitialize(gr->egl_display, &major, &minor)) {
1670 weston_log("failed to initialize display\n");
1671 goto err_egl;
1672 }
1673
1674 if (egl_choose_config(gr, attribs, visual_id) < 0) {
1675 weston_log("failed to choose EGL config\n");
1676 goto err_egl;
1677 }
1678
1679 ec->renderer = &gr->base;
Pekka Paalanen7bb65102013-05-22 18:03:04 +03001680 ec->capabilities |= WESTON_CAP_ROTATION_ANY;
Pekka Paalanen4fc5dd02013-05-22 18:03:05 +03001681 ec->capabilities |= WESTON_CAP_CAPTURE_YFLIP;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001682
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001683 wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565);
1684
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001685 return 0;
1686
1687err_egl:
Pekka Paalanen326529f2012-11-27 12:25:25 +02001688 gl_renderer_print_egl_error_state();
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001689 free(gr);
1690 return -1;
1691}
1692
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001693static EGLDisplay
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001694gl_renderer_display(struct weston_compositor *ec)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001695{
1696 return get_renderer(ec)->egl_display;
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001697}
1698
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001699static int
1700compile_shaders(struct weston_compositor *ec)
1701{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001702 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker40684142012-11-13 19:10:25 +01001703
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03001704 gr->texture_shader_rgba.vertex_source = vertex_shader;
1705 gr->texture_shader_rgba.fragment_source = texture_fragment_shader_rgba;
1706
1707 gr->texture_shader_rgbx.vertex_source = vertex_shader;
1708 gr->texture_shader_rgbx.fragment_source = texture_fragment_shader_rgbx;
1709
1710 gr->texture_shader_egl_external.vertex_source = vertex_shader;
1711 gr->texture_shader_egl_external.fragment_source =
1712 texture_fragment_shader_egl_external;
1713
1714 gr->texture_shader_y_uv.vertex_source = vertex_shader;
1715 gr->texture_shader_y_uv.fragment_source = texture_fragment_shader_y_uv;
1716
1717 gr->texture_shader_y_u_v.vertex_source = vertex_shader;
1718 gr->texture_shader_y_u_v.fragment_source =
1719 texture_fragment_shader_y_u_v;
1720
1721 gr->texture_shader_y_u_v.vertex_source = vertex_shader;
1722 gr->texture_shader_y_xuxv.fragment_source =
1723 texture_fragment_shader_y_xuxv;
1724
1725 gr->solid_shader.vertex_source = vertex_shader;
1726 gr->solid_shader.fragment_source = solid_fragment_shader;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001727
1728 return 0;
1729}
1730
1731static void
Kristian Høgsberge3148752013-05-06 23:19:49 -04001732fragment_debug_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001733 void *data)
1734{
1735 struct weston_compositor *ec = data;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001736 struct gl_renderer *gr = get_renderer(ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001737 struct weston_output *output;
1738
John Kåre Alsaker40684142012-11-13 19:10:25 +01001739 gr->fragment_shader_debug ^= 1;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001740
John Kåre Alsaker40684142012-11-13 19:10:25 +01001741 shader_release(&gr->texture_shader_rgba);
1742 shader_release(&gr->texture_shader_rgbx);
1743 shader_release(&gr->texture_shader_egl_external);
1744 shader_release(&gr->texture_shader_y_uv);
1745 shader_release(&gr->texture_shader_y_u_v);
1746 shader_release(&gr->texture_shader_y_xuxv);
1747 shader_release(&gr->solid_shader);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001748
Ander Conselvan de Oliveira03fb4ef2012-12-03 17:08:11 +02001749 /* Force use_shader() to call glUseProgram(), since we need to use
1750 * the recompiled version of the shader. */
1751 gr->current_shader = NULL;
1752
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001753 wl_list_for_each(output, &ec->output_list, link)
1754 weston_output_damage(output);
1755}
1756
Kristian Høgsberg8799d412013-05-07 10:50:09 -04001757static void
1758fan_debug_repaint_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
1759 void *data)
1760{
1761 struct weston_compositor *compositor = data;
1762 struct gl_renderer *gr = get_renderer(compositor);
1763
1764 gr->fan_debug = !gr->fan_debug;
1765 weston_compositor_damage_all(compositor);
1766}
1767
John Kåre Alsaker94659272012-11-13 19:10:18 +01001768static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001769gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001770{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001771 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001772 const char *extensions;
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001773 EGLBoolean ret;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001774
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001775 static const EGLint context_attribs[] = {
1776 EGL_CONTEXT_CLIENT_VERSION, 2,
1777 EGL_NONE
1778 };
1779
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001780 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
1781 weston_log("failed to bind EGL_OPENGL_ES_API\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001782 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001783 return -1;
1784 }
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001785
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001786 log_egl_config_info(gr->egl_display, gr->egl_config);
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001787
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001788 gr->egl_context = eglCreateContext(gr->egl_display, gr->egl_config,
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001789 EGL_NO_CONTEXT, context_attribs);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001790 if (gr->egl_context == NULL) {
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001791 weston_log("failed to create context\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001792 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001793 return -1;
1794 }
1795
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001796 ret = eglMakeCurrent(gr->egl_display, egl_surface,
1797 egl_surface, gr->egl_context);
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001798 if (ret == EGL_FALSE) {
1799 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001800 gl_renderer_print_egl_error_state();
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001801 return -1;
1802 }
1803
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001804 log_egl_gl_info(gr->egl_display);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001805
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001806 gr->image_target_texture_2d =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001807 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001808 gr->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
1809 gr->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
1810 gr->bind_display =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001811 (void *) eglGetProcAddress("eglBindWaylandDisplayWL");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001812 gr->unbind_display =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001813 (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001814 gr->query_buffer =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001815 (void *) eglGetProcAddress("eglQueryWaylandBufferWL");
1816
1817 extensions = (const char *) glGetString(GL_EXTENSIONS);
1818 if (!extensions) {
1819 weston_log("Retrieving GL extension string failed.\n");
1820 return -1;
1821 }
1822
1823 if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
1824 weston_log("GL_EXT_texture_format_BGRA8888 not available\n");
1825 return -1;
1826 }
1827
1828 if (strstr(extensions, "GL_EXT_read_format_bgra"))
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01001829 ec->read_format = PIXMAN_a8r8g8b8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001830 else
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01001831 ec->read_format = PIXMAN_a8b8g8r8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001832
Kristian Høgsberg1c4f1632013-08-07 12:11:27 -07001833#ifdef GL_EXT_unpack_subimage
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001834 if (strstr(extensions, "GL_EXT_unpack_subimage"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001835 gr->has_unpack_subimage = 1;
Kristian Høgsberg1c4f1632013-08-07 12:11:27 -07001836#endif
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001837
1838 if (strstr(extensions, "GL_OES_EGL_image_external"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001839 gr->has_egl_image_external = 1;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001840
1841 extensions =
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001842 (const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001843 if (!extensions) {
1844 weston_log("Retrieving EGL extension string failed.\n");
1845 return -1;
1846 }
1847
1848 if (strstr(extensions, "EGL_WL_bind_wayland_display"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001849 gr->has_bind_display = 1;
1850 if (gr->has_bind_display) {
1851 ret = gr->bind_display(gr->egl_display, ec->wl_display);
Pekka Paalanen035a0322012-10-24 09:43:06 +03001852 if (!ret)
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001853 gr->has_bind_display = 0;
Pekka Paalanen035a0322012-10-24 09:43:06 +03001854 }
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001855
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001856 if (strstr(extensions, "EGL_EXT_buffer_age"))
1857 gr->has_egl_buffer_age = 1;
1858 else
1859 weston_log("warning: EGL_EXT_buffer_age not supported. "
1860 "Performance could be affected.\n");
1861
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001862 glActiveTexture(GL_TEXTURE0);
1863
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001864 if (compile_shaders(ec))
1865 return -1;
1866
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +03001867 gr->fragment_binding =
1868 weston_compositor_add_debug_binding(ec, KEY_S,
1869 fragment_debug_binding,
1870 ec);
1871 gr->fan_binding =
1872 weston_compositor_add_debug_binding(ec, KEY_F,
1873 fan_debug_repaint_binding,
1874 ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001875
Pekka Paalanen035a0322012-10-24 09:43:06 +03001876 weston_log("GL ES 2 renderer features:\n");
1877 weston_log_continue(STAMP_SPACE "read-back format: %s\n",
Pekka Paalanenfe4eacf2013-01-10 16:50:42 +02001878 ec->read_format == PIXMAN_a8r8g8b8 ? "BGRA" : "RGBA");
Pekka Paalanen035a0322012-10-24 09:43:06 +03001879 weston_log_continue(STAMP_SPACE "wl_shm sub-image to texture: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001880 gr->has_unpack_subimage ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03001881 weston_log_continue(STAMP_SPACE "EGL Wayland extension: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001882 gr->has_bind_display ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03001883
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001884
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001885 return 0;
1886}
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001887
1888WL_EXPORT struct gl_renderer_interface gl_renderer_interface = {
1889 .opaque_attribs = gl_renderer_opaque_attribs,
1890 .alpha_attribs = gl_renderer_alpha_attribs,
1891
1892 .create = gl_renderer_create,
1893 .display = gl_renderer_display,
1894 .output_create = gl_renderer_output_create,
1895 .output_destroy = gl_renderer_output_destroy,
1896 .output_surface = gl_renderer_output_surface,
1897 .set_border = gl_renderer_set_border,
1898 .print_egl_error_state = gl_renderer_print_egl_error_state
1899};