blob: 0c0f2d9419e0d33e7424bc817bb59f82a67593c8 [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;
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +030082
83 struct weston_surface *surface;
84
85 struct wl_listener surface_destroy_listener;
John Kåre Alsaker878f4492012-11-13 19:10:23 +010086};
87
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010088struct gl_renderer {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +010089 struct weston_renderer base;
90 int fragment_shader_debug;
Kristian Høgsberg8799d412013-05-07 10:50:09 -040091 int fan_debug;
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +030092 struct weston_binding *fragment_binding;
93 struct weston_binding *fan_binding;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +010094
95 EGLDisplay egl_display;
96 EGLContext egl_context;
97 EGLConfig egl_config;
John Kåre Alsaker44154502012-11-13 19:10:20 +010098
99 struct {
100 int32_t top, bottom, left, right;
101 GLuint texture;
102 int32_t width, height;
103 } border;
John Kåre Alsaker40684142012-11-13 19:10:25 +0100104
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400105 struct wl_array vertices;
106 struct wl_array indices; /* only used in compositor-wayland */
107 struct wl_array vtxcnt;
108
John Kåre Alsaker320711d2012-11-13 19:10:27 +0100109 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
110 PFNEGLCREATEIMAGEKHRPROC create_image;
111 PFNEGLDESTROYIMAGEKHRPROC destroy_image;
112
113 int has_unpack_subimage;
114
115 PFNEGLBINDWAYLANDDISPLAYWL bind_display;
116 PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
117 PFNEGLQUERYWAYLANDBUFFERWL query_buffer;
118 int has_bind_display;
119
120 int has_egl_image_external;
121
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200122 int has_egl_buffer_age;
123
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100124 struct gl_shader texture_shader_rgba;
125 struct gl_shader texture_shader_rgbx;
126 struct gl_shader texture_shader_egl_external;
127 struct gl_shader texture_shader_y_uv;
128 struct gl_shader texture_shader_y_u_v;
129 struct gl_shader texture_shader_y_xuxv;
130 struct gl_shader invert_color_shader;
131 struct gl_shader solid_shader;
132 struct gl_shader *current_shader;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100133};
John Kåre Alsaker94659272012-11-13 19:10:18 +0100134
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100135static inline struct gl_output_state *
John Kåre Alsaker94659272012-11-13 19:10:18 +0100136get_output_state(struct weston_output *output)
137{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100138 return (struct gl_output_state *)output->renderer_state;
John Kåre Alsaker94659272012-11-13 19:10:18 +0100139}
140
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300141static int
142gl_renderer_create_surface(struct weston_surface *surface);
143
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100144static inline struct gl_surface_state *
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100145get_surface_state(struct weston_surface *surface)
146{
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300147 if (!surface->renderer_state)
148 gl_renderer_create_surface(surface);
149
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100150 return (struct gl_surface_state *)surface->renderer_state;
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100151}
152
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100153static inline struct gl_renderer *
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100154get_renderer(struct weston_compositor *ec)
155{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100156 return (struct gl_renderer *)ec->renderer;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100157}
158
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400159static const char *
160egl_error_string(EGLint code)
161{
162#define MYERRCODE(x) case x: return #x;
163 switch (code) {
164 MYERRCODE(EGL_SUCCESS)
165 MYERRCODE(EGL_NOT_INITIALIZED)
166 MYERRCODE(EGL_BAD_ACCESS)
167 MYERRCODE(EGL_BAD_ALLOC)
168 MYERRCODE(EGL_BAD_ATTRIBUTE)
169 MYERRCODE(EGL_BAD_CONTEXT)
170 MYERRCODE(EGL_BAD_CONFIG)
171 MYERRCODE(EGL_BAD_CURRENT_SURFACE)
172 MYERRCODE(EGL_BAD_DISPLAY)
173 MYERRCODE(EGL_BAD_SURFACE)
174 MYERRCODE(EGL_BAD_MATCH)
175 MYERRCODE(EGL_BAD_PARAMETER)
176 MYERRCODE(EGL_BAD_NATIVE_PIXMAP)
177 MYERRCODE(EGL_BAD_NATIVE_WINDOW)
178 MYERRCODE(EGL_CONTEXT_LOST)
179 default:
180 return "unknown";
181 }
182#undef MYERRCODE
183}
184
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +0300185static void
Pekka Paalanen326529f2012-11-27 12:25:25 +0200186gl_renderer_print_egl_error_state(void)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400187{
188 EGLint code;
189
190 code = eglGetError();
191 weston_log("EGL error state: %s (0x%04lx)\n",
192 egl_error_string(code), (long)code);
193}
194
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400195#define max(a, b) (((a) > (b)) ? (a) : (b))
196#define min(a, b) (((a) > (b)) ? (b) : (a))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400197
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300198/*
199 * Compute the boundary vertices of the intersection of the global coordinate
200 * aligned rectangle 'rect', and an arbitrary quadrilateral produced from
201 * 'surf_rect' when transformed from surface coordinates into global coordinates.
202 * The vertices are written to 'ex' and 'ey', and the return value is the
203 * number of vertices. Vertices are produced in clockwise winding order.
204 * Guarantees to produce either zero vertices, or 3-8 vertices with non-zero
205 * polygon area.
206 */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400207static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500208calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400209 pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
210{
Sam Spilsbury619859c2013-09-13 10:01:21 +0800211
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300212 struct clip_context ctx;
213 int i, n;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400214 GLfloat min_x, max_x, min_y, max_y;
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300215 struct polygon8 surf = {
216 { surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1 },
217 { surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2 },
218 4
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400219 };
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400220
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300221 ctx.clip.x1 = rect->x1;
222 ctx.clip.y1 = rect->y1;
223 ctx.clip.x2 = rect->x2;
224 ctx.clip.y2 = rect->y2;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400225
226 /* transform surface to screen space: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300227 for (i = 0; i < surf.n; i++)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500228 weston_view_to_global_float(ev, surf.x[i], surf.y[i],
229 &surf.x[i], &surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400230
231 /* find bounding box: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300232 min_x = max_x = surf.x[0];
233 min_y = max_y = surf.y[0];
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400234
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300235 for (i = 1; i < surf.n; i++) {
236 min_x = min(min_x, surf.x[i]);
237 max_x = max(max_x, surf.x[i]);
238 min_y = min(min_y, surf.y[i]);
239 max_y = max(max_y, surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400240 }
241
242 /* First, simple bounding box check to discard early transformed
243 * surface rects that do not intersect with the clip region:
244 */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300245 if ((min_x >= ctx.clip.x2) || (max_x <= ctx.clip.x1) ||
246 (min_y >= ctx.clip.y2) || (max_y <= ctx.clip.y1))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400247 return 0;
248
249 /* Simple case, bounding box edges are parallel to surface edges,
250 * there will be only four edges. We just need to clip the surface
251 * vertices to the clip rect bounds:
252 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500253 if (!ev->transform.enabled)
Sam Spilsbury619859c2013-09-13 10:01:21 +0800254 return clip_simple(&ctx, &surf, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400255
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300256 /* Transformed case: use a general polygon clipping algorithm to
257 * clip the surface rectangle with each side of 'rect'.
258 * The algorithm is Sutherland-Hodgman, as explained in
259 * http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm
260 * but without looking at any of that code.
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400261 */
Sam Spilsbury619859c2013-09-13 10:01:21 +0800262 n = clip_transformed(&ctx, &surf, ex, ey);
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300263
264 if (n < 3)
265 return 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400266
267 return n;
268}
269
270static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500271texture_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400272 pixman_region32_t *surf_region)
273{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500274 struct gl_surface_state *gs = get_surface_state(ev->surface);
275 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400276 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400277 GLfloat *v, inv_width, inv_height;
278 unsigned int *vtxcnt, nvtx = 0;
279 pixman_box32_t *rects, *surf_rects;
280 int i, j, k, nrects, nsurf;
281
282 rects = pixman_region32_rectangles(region, &nrects);
283 surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
284
285 /* worst case we can have 8 vertices per rect (ie. clipped into
286 * an octagon):
287 */
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400288 v = wl_array_add(&gr->vertices, nrects * nsurf * 8 * 4 * sizeof *v);
289 vtxcnt = wl_array_add(&gr->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400290
Pekka Paalanen68033ac2012-12-04 15:58:15 +0200291 inv_width = 1.0 / gs->pitch;
Alexander Larsson4ea95522013-05-22 14:41:37 +0200292 inv_height = 1.0 / gs->height;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400293
294 for (i = 0; i < nrects; i++) {
295 pixman_box32_t *rect = &rects[i];
296 for (j = 0; j < nsurf; j++) {
297 pixman_box32_t *surf_rect = &surf_rects[j];
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200298 GLfloat sx, sy, bx, by;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400299 GLfloat ex[8], ey[8]; /* edge points in screen space */
300 int n;
301
302 /* The transformed surface, after clipping to the clip region,
303 * can have as many as eight sides, emitted as a triangle-fan.
304 * The first vertex in the triangle fan can be chosen arbitrarily,
305 * since the area is guaranteed to be convex.
306 *
307 * If a corner of the transformed surface falls outside of the
308 * clip region, instead of emitting one vertex for the corner
309 * of the surface, up to two are emitted for two corresponding
310 * intersection point(s) between the surface and the clip region.
311 *
312 * To do this, we first calculate the (up to eight) points that
313 * form the intersection of the clip rect and the transformed
314 * surface.
315 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500316 n = calculate_edges(ev, rect, surf_rect, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400317 if (n < 3)
318 continue;
319
320 /* emit edge points: */
321 for (k = 0; k < n; k++) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500322 weston_view_from_global_float(ev, ex[k], ey[k],
323 &sx, &sy);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400324 /* position: */
325 *(v++) = ex[k];
326 *(v++) = ey[k];
327 /* texcoord: */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500328 weston_surface_to_buffer_float(ev->surface,
329 sx, sy,
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200330 &bx, &by);
331 *(v++) = bx * inv_width;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +0400332 if (gs->y_inverted) {
333 *(v++) = by * inv_height;
334 } else {
335 *(v++) = (gs->height - by) * inv_height;
336 }
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400337 }
338
339 vtxcnt[nvtx++] = n;
340 }
341 }
342
343 return nvtx;
344}
345
346static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500347triangle_fan_debug(struct weston_view *view, int first, int count)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400348{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500349 struct weston_compositor *compositor = view->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100350 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400351 int i;
352 GLushort *buffer;
353 GLushort *index;
354 int nelems;
355 static int color_idx = 0;
356 static const GLfloat color[][4] = {
357 { 1.0, 0.0, 0.0, 1.0 },
358 { 0.0, 1.0, 0.0, 1.0 },
359 { 0.0, 0.0, 1.0, 1.0 },
360 { 1.0, 1.0, 1.0, 1.0 },
361 };
362
363 nelems = (count - 1 + count - 2) * 2;
364
365 buffer = malloc(sizeof(GLushort) * nelems);
366 index = buffer;
367
368 for (i = 1; i < count; i++) {
369 *index++ = first;
370 *index++ = first + i;
371 }
372
373 for (i = 2; i < count; i++) {
374 *index++ = first + i - 1;
375 *index++ = first + i;
376 }
377
John Kåre Alsaker40684142012-11-13 19:10:25 +0100378 glUseProgram(gr->solid_shader.program);
379 glUniform4fv(gr->solid_shader.color_uniform, 1,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400380 color[color_idx++ % ARRAY_LENGTH(color)]);
381 glDrawElements(GL_LINES, nelems, GL_UNSIGNED_SHORT, buffer);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100382 glUseProgram(gr->current_shader->program);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400383 free(buffer);
384}
385
386static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500387repaint_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400388 pixman_region32_t *surf_region)
389{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500390 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400391 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400392 GLfloat *v;
393 unsigned int *vtxcnt;
394 int i, first, nfans;
395
396 /* The final region to be painted is the intersection of
397 * 'region' and 'surf_region'. However, 'region' is in the global
398 * coordinates, and 'surf_region' is in the surface-local
399 * coordinates. texture_region() will iterate over all pairs of
400 * rectangles from both regions, compute the intersection
401 * polygon for each pair, and store it as a triangle fan if
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400402 * it has a non-zero area (at least 3 vertices1, actually).
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400403 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500404 nfans = texture_region(ev, region, surf_region);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400405
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400406 v = gr->vertices.data;
407 vtxcnt = gr->vtxcnt.data;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400408
409 /* position: */
410 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
411 glEnableVertexAttribArray(0);
412
413 /* texcoord: */
414 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
415 glEnableVertexAttribArray(1);
416
417 for (i = 0, first = 0; i < nfans; i++) {
418 glDrawArrays(GL_TRIANGLE_FAN, first, vtxcnt[i]);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400419 if (gr->fan_debug)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500420 triangle_fan_debug(ev, first, vtxcnt[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400421 first += vtxcnt[i];
422 }
423
424 glDisableVertexAttribArray(1);
425 glDisableVertexAttribArray(0);
426
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400427 gr->vertices.size = 0;
428 gr->vtxcnt.size = 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400429}
430
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100431static int
432use_output(struct weston_output *output)
433{
434 static int errored;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100435 struct gl_output_state *go = get_output_state(output);
436 struct gl_renderer *gr = get_renderer(output->compositor);
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100437 EGLBoolean ret;
438
439 ret = eglMakeCurrent(gr->egl_display, go->egl_surface,
440 go->egl_surface, gr->egl_context);
441
442 if (ret == EGL_FALSE) {
443 if (errored)
444 return -1;
445 errored = 1;
446 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +0200447 gl_renderer_print_egl_error_state();
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100448 return -1;
449 }
450
451 return 0;
452}
453
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300454static int
455shader_init(struct gl_shader *shader, struct gl_renderer *gr,
456 const char *vertex_source, const char *fragment_source);
457
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400458static void
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300459use_shader(struct gl_renderer *gr, struct gl_shader *shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400460{
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300461 if (!shader->program) {
462 int ret;
463
464 ret = shader_init(shader, gr,
465 shader->vertex_source,
466 shader->fragment_source);
467
468 if (ret < 0)
469 weston_log("warning: failed to compile shader\n");
470 }
471
John Kåre Alsaker40684142012-11-13 19:10:25 +0100472 if (gr->current_shader == shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400473 return;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400474 glUseProgram(shader->program);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100475 gr->current_shader = shader;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400476}
477
478static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100479shader_uniforms(struct gl_shader *shader,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500480 struct weston_view *view,
481 struct weston_output *output)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400482{
483 int i;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500484 struct gl_surface_state *gs = get_surface_state(view->surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400485
486 glUniformMatrix4fv(shader->proj_uniform,
487 1, GL_FALSE, output->matrix.d);
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100488 glUniform4fv(shader->color_uniform, 1, gs->color);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500489 glUniform1f(shader->alpha_uniform, view->alpha);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400490
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100491 for (i = 0; i < gs->num_textures; i++)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400492 glUniform1i(shader->tex_uniforms[i], i);
493}
494
495static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500496draw_view(struct weston_view *ev, struct weston_output *output,
497 pixman_region32_t *damage) /* in global coordinates */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400498{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500499 struct weston_compositor *ec = ev->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100500 struct gl_renderer *gr = get_renderer(ec);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500501 struct gl_surface_state *gs = get_surface_state(ev->surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400502 /* repaint bounding region in global coordinates: */
503 pixman_region32_t repaint;
504 /* non-opaque region in surface coordinates: */
505 pixman_region32_t surface_blend;
506 GLint filter;
507 int i;
508
509 pixman_region32_init(&repaint);
510 pixman_region32_intersect(&repaint,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500511 &ev->transform.boundingbox, damage);
512 pixman_region32_subtract(&repaint, &repaint, &ev->clip);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400513
514 if (!pixman_region32_not_empty(&repaint))
515 goto out;
516
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400517 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
518
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400519 if (gr->fan_debug) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100520 use_shader(gr, &gr->solid_shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500521 shader_uniforms(&gr->solid_shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400522 }
523
John Kåre Alsaker40684142012-11-13 19:10:25 +0100524 use_shader(gr, gs->shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500525 shader_uniforms(gs->shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400526
Jason Ekstranda7af7042013-10-12 22:38:11 -0500527 if (ev->transform.enabled || output->zoom.active ||
528 output->current_scale != ev->surface->buffer_scale)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400529 filter = GL_LINEAR;
530 else
531 filter = GL_NEAREST;
532
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100533 for (i = 0; i < gs->num_textures; i++) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400534 glActiveTexture(GL_TEXTURE0 + i);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100535 glBindTexture(gs->target, gs->textures[i]);
536 glTexParameteri(gs->target, GL_TEXTURE_MIN_FILTER, filter);
537 glTexParameteri(gs->target, GL_TEXTURE_MAG_FILTER, filter);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400538 }
539
540 /* blended region is whole surface minus opaque region: */
541 pixman_region32_init_rect(&surface_blend, 0, 0,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500542 ev->geometry.width, ev->geometry.height);
543 pixman_region32_subtract(&surface_blend, &surface_blend, &ev->surface->opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400544
Jason Ekstranda7af7042013-10-12 22:38:11 -0500545 /* XXX: Should we be using ev->transform.opaque here? */
546 if (pixman_region32_not_empty(&ev->surface->opaque)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100547 if (gs->shader == &gr->texture_shader_rgba) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400548 /* Special case for RGBA textures with possibly
549 * bad data in alpha channel: use the shader
550 * that forces texture alpha = 1.0.
551 * Xwayland surfaces need this.
552 */
John Kåre Alsaker40684142012-11-13 19:10:25 +0100553 use_shader(gr, &gr->texture_shader_rgbx);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500554 shader_uniforms(&gr->texture_shader_rgbx, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400555 }
556
Jason Ekstranda7af7042013-10-12 22:38:11 -0500557 if (ev->alpha < 1.0)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400558 glEnable(GL_BLEND);
559 else
560 glDisable(GL_BLEND);
561
Jason Ekstranda7af7042013-10-12 22:38:11 -0500562 repaint_region(ev, &repaint, &ev->surface->opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400563 }
564
565 if (pixman_region32_not_empty(&surface_blend)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100566 use_shader(gr, gs->shader);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400567 glEnable(GL_BLEND);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500568 repaint_region(ev, &repaint, &surface_blend);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400569 }
570
571 pixman_region32_fini(&surface_blend);
572
573out:
574 pixman_region32_fini(&repaint);
575}
576
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400577static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500578repaint_views(struct weston_output *output, pixman_region32_t *damage)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400579{
580 struct weston_compositor *compositor = output->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500581 struct weston_view *view;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400582
Jason Ekstranda7af7042013-10-12 22:38:11 -0500583 wl_list_for_each_reverse(view, &compositor->view_list, link)
584 if (view->plane == &compositor->primary_plane)
585 draw_view(view, output, damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400586}
587
John Kåre Alsaker44154502012-11-13 19:10:20 +0100588
589static int
590texture_border(struct weston_output *output)
591{
592 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100593 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100594 GLfloat *d;
Kristian Høgsberg73db9242013-08-28 23:05:29 -0700595 unsigned short *p;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100596 int i, j, k, n;
597 GLfloat x[4], y[4], u[4], v[4];
598
599 x[0] = -gr->border.left;
600 x[1] = 0;
Hardeningff39efa2013-09-18 23:56:35 +0200601 x[2] = output->current_mode->width;
602 x[3] = output->current_mode->width + gr->border.right;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100603
604 y[0] = -gr->border.top;
605 y[1] = 0;
Hardeningff39efa2013-09-18 23:56:35 +0200606 y[2] = output->current_mode->height;
607 y[3] = output->current_mode->height + gr->border.bottom;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100608
609 u[0] = 0.0;
610 u[1] = (GLfloat) gr->border.left / gr->border.width;
611 u[2] = (GLfloat) (gr->border.width - gr->border.right) / gr->border.width;
612 u[3] = 1.0;
613
614 v[0] = 0.0;
615 v[1] = (GLfloat) gr->border.top / gr->border.height;
616 v[2] = (GLfloat) (gr->border.height - gr->border.bottom) / gr->border.height;
617 v[3] = 1.0;
618
619 n = 8;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400620 d = wl_array_add(&gr->vertices, n * 16 * sizeof *d);
621 p = wl_array_add(&gr->indices, n * 6 * sizeof *p);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100622
623 k = 0;
624 for (i = 0; i < 3; i++)
625 for (j = 0; j < 3; j++) {
626
627 if (i == 1 && j == 1)
628 continue;
629
630 d[ 0] = x[i];
631 d[ 1] = y[j];
632 d[ 2] = u[i];
633 d[ 3] = v[j];
634
635 d[ 4] = x[i];
636 d[ 5] = y[j + 1];
637 d[ 6] = u[i];
638 d[ 7] = v[j + 1];
639
640 d[ 8] = x[i + 1];
641 d[ 9] = y[j];
642 d[10] = u[i + 1];
643 d[11] = v[j];
644
645 d[12] = x[i + 1];
646 d[13] = y[j + 1];
647 d[14] = u[i + 1];
648 d[15] = v[j + 1];
649
650 p[0] = k + 0;
651 p[1] = k + 1;
652 p[2] = k + 2;
653 p[3] = k + 2;
654 p[4] = k + 1;
655 p[5] = k + 3;
656
657 d += 16;
658 p += 6;
659 k += 4;
660 }
661
662 return k / 4;
663}
664
665static void
666draw_border(struct weston_output *output)
667{
668 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100669 struct gl_renderer *gr = get_renderer(ec);
670 struct gl_shader *shader = &gr->texture_shader_rgba;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100671 GLfloat *v;
672 int n;
673
674 glDisable(GL_BLEND);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100675 use_shader(gr, shader);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100676
677 glUniformMatrix4fv(shader->proj_uniform,
678 1, GL_FALSE, output->matrix.d);
679
680 glUniform1i(shader->tex_uniforms[0], 0);
681 glUniform1f(shader->alpha_uniform, 1);
682
683 n = texture_border(output);
684
685 glActiveTexture(GL_TEXTURE0);
686 glBindTexture(GL_TEXTURE_2D, gr->border.texture);
687
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400688 v = gr->vertices.data;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100689 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
690 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
691 glEnableVertexAttribArray(0);
692 glEnableVertexAttribArray(1);
693
694 glDrawElements(GL_TRIANGLES, n * 6,
Kristian Høgsberg73db9242013-08-28 23:05:29 -0700695 GL_UNSIGNED_SHORT, gr->indices.data);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100696
697 glDisableVertexAttribArray(1);
698 glDisableVertexAttribArray(0);
699
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400700 gr->vertices.size = 0;
701 gr->indices.size = 0;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100702}
703
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400704static void
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200705output_get_buffer_damage(struct weston_output *output,
706 pixman_region32_t *buffer_damage)
707{
708 struct gl_output_state *go = get_output_state(output);
709 struct gl_renderer *gr = get_renderer(output->compositor);
710 EGLint buffer_age = 0;
711 EGLBoolean ret;
712 int i;
713
714 if (gr->has_egl_buffer_age) {
715 ret = eglQuerySurface(gr->egl_display, go->egl_surface,
716 EGL_BUFFER_AGE_EXT, &buffer_age);
717 if (ret == EGL_FALSE) {
718 weston_log("buffer age query failed.\n");
719 gl_renderer_print_egl_error_state();
720 }
721 }
722
723 if (buffer_age == 0 || buffer_age - 1 > BUFFER_DAMAGE_COUNT)
724 pixman_region32_copy(buffer_damage, &output->region);
725 else
726 for (i = 0; i < buffer_age - 1; i++)
727 pixman_region32_union(buffer_damage, buffer_damage,
728 &go->buffer_damage[i]);
729}
730
731static void
732output_rotate_damage(struct weston_output *output,
733 pixman_region32_t *output_damage)
734{
735 struct gl_output_state *go = get_output_state(output);
736 struct gl_renderer *gr = get_renderer(output->compositor);
737 int i;
738
739 if (!gr->has_egl_buffer_age)
740 return;
741
742 for (i = BUFFER_DAMAGE_COUNT - 1; i >= 1; i--)
743 pixman_region32_copy(&go->buffer_damage[i],
744 &go->buffer_damage[i - 1]);
745
746 pixman_region32_copy(&go->buffer_damage[0], output_damage);
747}
748
749static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100750gl_renderer_repaint_output(struct weston_output *output,
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400751 pixman_region32_t *output_damage)
752{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100753 struct gl_output_state *go = get_output_state(output);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400754 struct weston_compositor *compositor = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100755 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400756 EGLBoolean ret;
757 static int errored;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200758 int32_t width, height;
759 pixman_region32_t buffer_damage, total_damage;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400760
Hardeningff39efa2013-09-18 23:56:35 +0200761 width = output->current_mode->width +
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400762 output->border.left + output->border.right;
Hardeningff39efa2013-09-18 23:56:35 +0200763 height = output->current_mode->height +
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400764 output->border.top + output->border.bottom;
765
766 glViewport(0, 0, width, height);
767
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100768 if (use_output(output) < 0)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400769 return;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400770
771 /* if debugging, redraw everything outside the damage to clean up
772 * debug lines from the previous draw on this buffer:
773 */
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400774 if (gr->fan_debug) {
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400775 pixman_region32_t undamaged;
776 pixman_region32_init(&undamaged);
777 pixman_region32_subtract(&undamaged, &output->region,
778 output_damage);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400779 gr->fan_debug = 0;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500780 repaint_views(output, &undamaged);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400781 gr->fan_debug = 1;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400782 pixman_region32_fini(&undamaged);
783 }
784
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +0200785 pixman_region32_init(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200786 pixman_region32_init(&buffer_damage);
787
788 output_get_buffer_damage(output, &buffer_damage);
789 output_rotate_damage(output, output_damage);
790
791 pixman_region32_union(&total_damage, &buffer_damage, output_damage);
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300792
Jason Ekstranda7af7042013-10-12 22:38:11 -0500793 repaint_views(output, &total_damage);
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +0200794
795 pixman_region32_fini(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200796 pixman_region32_fini(&buffer_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400797
John Kåre Alsaker44154502012-11-13 19:10:20 +0100798 if (gr->border.texture)
799 draw_border(output);
800
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +0200801 pixman_region32_copy(&output->previous_damage, output_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400802 wl_signal_emit(&output->frame_signal, output);
803
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100804 ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400805 if (ret == EGL_FALSE && !errored) {
806 errored = 1;
807 weston_log("Failed in eglSwapBuffers.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +0200808 gl_renderer_print_egl_error_state();
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400809 }
810
811}
Kristian Høgsberg25894fc2012-09-05 22:06:26 -0400812
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100813static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100814gl_renderer_read_pixels(struct weston_output *output,
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100815 pixman_format_code_t format, void *pixels,
816 uint32_t x, uint32_t y,
817 uint32_t width, uint32_t height)
818{
819 GLenum gl_format;
820
821 switch (format) {
822 case PIXMAN_a8r8g8b8:
823 gl_format = GL_BGRA_EXT;
824 break;
825 case PIXMAN_a8b8g8r8:
826 gl_format = GL_RGBA;
827 break;
828 default:
829 return -1;
830 }
831
832 if (use_output(output) < 0)
833 return -1;
834
835 glPixelStorei(GL_PACK_ALIGNMENT, 1);
836 glReadPixels(x, y, width, height, gl_format,
837 GL_UNSIGNED_BYTE, pixels);
838
839 return 0;
840}
841
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400842static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100843gl_renderer_flush_damage(struct weston_surface *surface)
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400844{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100845 struct gl_renderer *gr = get_renderer(surface->compositor);
846 struct gl_surface_state *gs = get_surface_state(surface);
Jason Ekstrand6bd62942013-06-20 20:38:23 -0500847 struct weston_buffer *buffer = gs->buffer_ref.buffer;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500848 struct weston_view *view;
849 int texture_used;
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200850 GLenum format;
851 int pixel_type;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100852
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700853#ifdef GL_EXT_unpack_subimage
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400854 pixman_box32_t *rectangles;
855 void *data;
856 int i, n;
857#endif
858
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200859 pixman_region32_union(&gs->texture_damage,
860 &gs->texture_damage, &surface->damage);
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200861
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200862 if (!buffer)
863 return;
864
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200865 /* Avoid upload, if the texture won't be used this time.
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200866 * We still accumulate the damage in texture_damage, and
867 * hold the reference to the buffer, in case the surface
868 * migrates back to the primary plane.
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200869 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500870 texture_used = 0;
871 wl_list_for_each(view, &surface->views, surface_link) {
872 if (view->plane == &surface->compositor->primary_plane) {
873 texture_used = 1;
874 break;
875 }
876 }
877 if (!texture_used)
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200878 return;
879
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200880 if (!pixman_region32_not_empty(&gs->texture_damage))
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200881 goto done;
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200882
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200883 switch (wl_shm_buffer_get_format(buffer->shm_buffer)) {
884 case WL_SHM_FORMAT_XRGB8888:
885 case WL_SHM_FORMAT_ARGB8888:
886 format = GL_BGRA_EXT;
887 pixel_type = GL_UNSIGNED_BYTE;
888 break;
889 case WL_SHM_FORMAT_RGB565:
890 format = GL_RGB;
891 pixel_type = GL_UNSIGNED_SHORT_5_6_5;
892 break;
893 default:
894 weston_log("warning: unknown shm buffer format\n");
895 format = GL_BGRA_EXT;
896 pixel_type = GL_UNSIGNED_BYTE;
897 }
898
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100899 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400900
John Kåre Alsaker320711d2012-11-13 19:10:27 +0100901 if (!gr->has_unpack_subimage) {
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200902 glTexImage2D(GL_TEXTURE_2D, 0, format,
Pekka Paalanen68033ac2012-12-04 15:58:15 +0200903 gs->pitch, buffer->height, 0,
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200904 format, pixel_type,
Jason Ekstrand6bd62942013-06-20 20:38:23 -0500905 wl_shm_buffer_get_data(buffer->shm_buffer));
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400906
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200907 goto done;
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400908 }
909
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700910#ifdef GL_EXT_unpack_subimage
911 glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, gs->pitch);
Jason Ekstrand6bd62942013-06-20 20:38:23 -0500912 data = wl_shm_buffer_get_data(buffer->shm_buffer);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300913
914 if (gs->needs_full_upload) {
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700915 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
916 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300917 glTexSubImage2D(GL_TEXTURE_2D, 0,
918 0, 0, gs->pitch, buffer->height,
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200919 format, pixel_type, data);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300920 goto done;
921 }
922
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200923 rectangles = pixman_region32_rectangles(&gs->texture_damage, &n);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400924 for (i = 0; i < n; i++) {
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200925 pixman_box32_t r;
926
927 r = weston_surface_to_buffer_rect(surface, rectangles[i]);
928
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700929 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, r.x1);
930 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, r.y1);
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200931 glTexSubImage2D(GL_TEXTURE_2D, 0, r.x1, r.y1,
932 r.x2 - r.x1, r.y2 - r.y1,
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200933 format, pixel_type, data);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400934 }
935#endif
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200936
937done:
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200938 pixman_region32_fini(&gs->texture_damage);
939 pixman_region32_init(&gs->texture_damage);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300940 gs->needs_full_upload = 0;
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200941
942 weston_buffer_reference(&gs->buffer_ref, NULL);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400943}
944
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400945static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100946ensure_textures(struct gl_surface_state *gs, int num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400947{
948 int i;
949
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100950 if (num_textures <= gs->num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400951 return;
952
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100953 for (i = gs->num_textures; i < num_textures; i++) {
954 glGenTextures(1, &gs->textures[i]);
955 glBindTexture(gs->target, gs->textures[i]);
956 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400957 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100958 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400959 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
960 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100961 gs->num_textures = num_textures;
962 glBindTexture(gs->target, 0);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400963}
964
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400965static void
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +0300966gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
967 struct wl_shm_buffer *shm_buffer)
968{
969 struct weston_compositor *ec = es->compositor;
970 struct gl_renderer *gr = get_renderer(ec);
971 struct gl_surface_state *gs = get_surface_state(es);
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200972 int pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +0300973
974 buffer->shm_buffer = shm_buffer;
975 buffer->width = wl_shm_buffer_get_width(shm_buffer);
976 buffer->height = wl_shm_buffer_get_height(shm_buffer);
977
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200978 switch (wl_shm_buffer_get_format(shm_buffer)) {
979 case WL_SHM_FORMAT_XRGB8888:
980 gs->shader = &gr->texture_shader_rgbx;
981 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
982 break;
983 case WL_SHM_FORMAT_ARGB8888:
984 gs->shader = &gr->texture_shader_rgba;
985 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
986 break;
987 case WL_SHM_FORMAT_RGB565:
988 gs->shader = &gr->texture_shader_rgbx;
989 pitch = wl_shm_buffer_get_stride(shm_buffer) / 2;
990 break;
991 default:
992 weston_log("warning: unknown shm buffer format\n");
993 gs->shader = &gr->texture_shader_rgba;
994 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
995 }
996
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +0300997 /* Only allocate a texture if it doesn't match existing one.
998 * If a switch from DRM allocated buffer to a SHM buffer is
999 * happening, we need to allocate a new texture buffer. */
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001000 if (pitch != gs->pitch ||
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001001 buffer->height != gs->height ||
1002 gs->buffer_type != BUFFER_TYPE_SHM) {
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001003 gs->pitch = pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001004 gs->height = buffer->height;
1005 gs->target = GL_TEXTURE_2D;
1006 gs->buffer_type = BUFFER_TYPE_SHM;
1007 gs->needs_full_upload = 1;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001008 gs->y_inverted = 1;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001009
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001010 gs->surface = es;
1011
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001012 ensure_textures(gs, 1);
1013 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
1014 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1015 gs->pitch, buffer->height, 0,
1016 GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
1017 }
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001018}
1019
1020static void
1021gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
1022 uint32_t format)
1023{
1024 struct weston_compositor *ec = es->compositor;
1025 struct gl_renderer *gr = get_renderer(ec);
1026 struct gl_surface_state *gs = get_surface_state(es);
1027 EGLint attribs[3];
1028 int i, num_planes;
1029
1030 buffer->legacy_buffer = (struct wl_buffer *)buffer->resource;
1031 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1032 EGL_WIDTH, &buffer->width);
1033 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1034 EGL_HEIGHT, &buffer->height);
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001035 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1036 EGL_WAYLAND_Y_INVERTED_WL, &buffer->y_inverted);
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001037
1038 for (i = 0; i < gs->num_images; i++)
1039 gr->destroy_image(gr->egl_display, gs->images[i]);
1040 gs->num_images = 0;
1041 gs->target = GL_TEXTURE_2D;
1042 switch (format) {
1043 case EGL_TEXTURE_RGB:
1044 case EGL_TEXTURE_RGBA:
1045 default:
1046 num_planes = 1;
1047 gs->shader = &gr->texture_shader_rgba;
1048 break;
1049 case EGL_TEXTURE_EXTERNAL_WL:
1050 num_planes = 1;
1051 gs->target = GL_TEXTURE_EXTERNAL_OES;
1052 gs->shader = &gr->texture_shader_egl_external;
1053 break;
1054 case EGL_TEXTURE_Y_UV_WL:
1055 num_planes = 2;
1056 gs->shader = &gr->texture_shader_y_uv;
1057 break;
1058 case EGL_TEXTURE_Y_U_V_WL:
1059 num_planes = 3;
1060 gs->shader = &gr->texture_shader_y_u_v;
1061 break;
1062 case EGL_TEXTURE_Y_XUXV_WL:
1063 num_planes = 2;
1064 gs->shader = &gr->texture_shader_y_xuxv;
1065 break;
1066 }
1067
1068 ensure_textures(gs, num_planes);
1069 for (i = 0; i < num_planes; i++) {
1070 attribs[0] = EGL_WAYLAND_PLANE_WL;
1071 attribs[1] = i;
1072 attribs[2] = EGL_NONE;
1073 gs->images[i] = gr->create_image(gr->egl_display,
1074 NULL,
1075 EGL_WAYLAND_BUFFER_WL,
1076 buffer->legacy_buffer,
1077 attribs);
1078 if (!gs->images[i]) {
1079 weston_log("failed to create img for plane %d\n", i);
1080 continue;
1081 }
1082 gs->num_images++;
1083
1084 glActiveTexture(GL_TEXTURE0 + i);
1085 glBindTexture(gs->target, gs->textures[i]);
1086 gr->image_target_texture_2d(gs->target,
1087 gs->images[i]);
1088 }
1089
1090 gs->pitch = buffer->width;
1091 gs->height = buffer->height;
1092 gs->buffer_type = BUFFER_TYPE_EGL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001093 gs->y_inverted = buffer->y_inverted;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001094}
1095
1096static void
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001097gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001098{
1099 struct weston_compositor *ec = es->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001100 struct gl_renderer *gr = get_renderer(ec);
1101 struct gl_surface_state *gs = get_surface_state(es);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001102 struct wl_shm_buffer *shm_buffer;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001103 EGLint format;
1104 int i;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001105
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001106 weston_buffer_reference(&gs->buffer_ref, buffer);
1107
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001108 if (!buffer) {
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001109 for (i = 0; i < gs->num_images; i++) {
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001110 gr->destroy_image(gr->egl_display, gs->images[i]);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001111 gs->images[i] = NULL;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001112 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001113 gs->num_images = 0;
1114 glDeleteTextures(gs->num_textures, gs->textures);
1115 gs->num_textures = 0;
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001116 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001117 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001118 return;
1119 }
1120
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001121 shm_buffer = wl_shm_buffer_get(buffer->resource);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001122
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001123 if (shm_buffer)
1124 gl_renderer_attach_shm(es, buffer, shm_buffer);
Kristian Høgsberg47229392013-08-07 11:59:54 -07001125 else if (gr->query_buffer(gr->egl_display, (void *) buffer->resource,
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001126 EGL_TEXTURE_FORMAT, &format))
1127 gl_renderer_attach_egl(es, buffer, format);
1128 else {
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001129 weston_log("unhandled buffer type!\n");
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001130 weston_buffer_reference(&gs->buffer_ref, NULL);
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001131 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001132 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001133 }
1134}
1135
Kristian Høgsberg42263852012-09-06 21:59:29 -04001136static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001137gl_renderer_surface_set_color(struct weston_surface *surface,
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001138 float red, float green, float blue, float alpha)
1139{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001140 struct gl_surface_state *gs = get_surface_state(surface);
1141 struct gl_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001142
1143 gs->color[0] = red;
1144 gs->color[1] = green;
1145 gs->color[2] = blue;
1146 gs->color[3] = alpha;
1147
John Kåre Alsaker40684142012-11-13 19:10:25 +01001148 gs->shader = &gr->solid_shader;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001149}
1150
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001151static void
1152surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
1153{
1154 struct gl_surface_state *gs;
1155 struct gl_renderer *gr;
1156 struct weston_surface *surface = data;
1157 int i;
1158
1159 gr = get_renderer(surface->compositor);
1160
1161 gs = container_of(listener, struct gl_surface_state,
1162 surface_destroy_listener);
1163
1164 gs->surface->renderer_state = NULL;
1165
1166 glDeleteTextures(gs->num_textures, gs->textures);
1167
1168 for (i = 0; i < gs->num_images; i++)
1169 gr->destroy_image(gr->egl_display, gs->images[i]);
1170
1171 weston_buffer_reference(&gs->buffer_ref, NULL);
1172 pixman_region32_fini(&gs->texture_damage);
1173 free(gs);
1174}
1175
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001176static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001177gl_renderer_create_surface(struct weston_surface *surface)
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001178{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001179 struct gl_surface_state *gs;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001180
1181 gs = calloc(1, sizeof *gs);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001182 if (!gs)
1183 return -1;
1184
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001185 /* A buffer is never attached to solid color surfaces, yet
1186 * they still go through texcoord computations. Do not divide
1187 * by zero there.
1188 */
1189 gs->pitch = 1;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001190 gs->y_inverted = 1;
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001191
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001192 pixman_region32_init(&gs->texture_damage);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001193 surface->renderer_state = gs;
1194
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001195 gs->surface_destroy_listener.notify =
1196 surface_state_handle_surface_destroy;
1197 wl_signal_add(&surface->destroy_signal,
1198 &gs->surface_destroy_listener);
1199
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001200 return 0;
1201}
1202
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001203static const char vertex_shader[] =
1204 "uniform mat4 proj;\n"
1205 "attribute vec2 position;\n"
1206 "attribute vec2 texcoord;\n"
1207 "varying vec2 v_texcoord;\n"
1208 "void main()\n"
1209 "{\n"
1210 " gl_Position = proj * vec4(position, 0.0, 1.0);\n"
1211 " v_texcoord = texcoord;\n"
1212 "}\n";
1213
1214/* Declare common fragment shader uniforms */
1215#define FRAGMENT_CONVERT_YUV \
1216 " y *= alpha;\n" \
1217 " u *= alpha;\n" \
1218 " v *= alpha;\n" \
1219 " gl_FragColor.r = y + 1.59602678 * v;\n" \
1220 " gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n" \
1221 " gl_FragColor.b = y + 2.01723214 * u;\n" \
1222 " gl_FragColor.a = alpha;\n"
1223
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001224static const char fragment_debug[] =
1225 " gl_FragColor = vec4(0.0, 0.3, 0.0, 0.2) + gl_FragColor * 0.8;\n";
1226
1227static const char fragment_brace[] =
1228 "}\n";
1229
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001230static const char texture_fragment_shader_rgba[] =
1231 "precision mediump float;\n"
1232 "varying vec2 v_texcoord;\n"
1233 "uniform sampler2D tex;\n"
1234 "uniform float alpha;\n"
1235 "void main()\n"
1236 "{\n"
1237 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001238 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001239
1240static const char texture_fragment_shader_rgbx[] =
1241 "precision mediump float;\n"
1242 "varying vec2 v_texcoord;\n"
1243 "uniform sampler2D tex;\n"
1244 "uniform float alpha;\n"
1245 "void main()\n"
1246 "{\n"
1247 " gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb\n;"
1248 " gl_FragColor.a = alpha;\n"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001249 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001250
1251static const char texture_fragment_shader_egl_external[] =
1252 "#extension GL_OES_EGL_image_external : require\n"
1253 "precision mediump float;\n"
1254 "varying vec2 v_texcoord;\n"
1255 "uniform samplerExternalOES tex;\n"
1256 "uniform float alpha;\n"
1257 "void main()\n"
1258 "{\n"
1259 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
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_uv[] =
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).r - 0.5;\n"
1271 " float v = texture2D(tex1, v_texcoord).g - 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 texture_fragment_shader_y_u_v[] =
1276 "precision mediump float;\n"
1277 "uniform sampler2D tex;\n"
1278 "uniform sampler2D tex1;\n"
1279 "uniform sampler2D tex2;\n"
1280 "varying vec2 v_texcoord;\n"
1281 "uniform float alpha;\n"
1282 "void main() {\n"
1283 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1284 " float u = texture2D(tex1, v_texcoord).x - 0.5;\n"
1285 " float v = texture2D(tex2, v_texcoord).x - 0.5;\n"
1286 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001287 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001288
1289static const char texture_fragment_shader_y_xuxv[] =
1290 "precision mediump float;\n"
1291 "uniform sampler2D tex;\n"
1292 "uniform sampler2D tex1;\n"
1293 "varying vec2 v_texcoord;\n"
1294 "uniform float alpha;\n"
1295 "void main() {\n"
1296 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1297 " float u = texture2D(tex1, v_texcoord).g - 0.5;\n"
1298 " float v = texture2D(tex1, v_texcoord).a - 0.5;\n"
1299 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001300 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001301
1302static const char solid_fragment_shader[] =
1303 "precision mediump float;\n"
1304 "uniform vec4 color;\n"
1305 "uniform float alpha;\n"
1306 "void main()\n"
1307 "{\n"
1308 " gl_FragColor = alpha * color\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001309 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001310
1311static int
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001312compile_shader(GLenum type, int count, const char **sources)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001313{
1314 GLuint s;
1315 char msg[512];
1316 GLint status;
1317
1318 s = glCreateShader(type);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001319 glShaderSource(s, count, sources, NULL);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001320 glCompileShader(s);
1321 glGetShaderiv(s, GL_COMPILE_STATUS, &status);
1322 if (!status) {
1323 glGetShaderInfoLog(s, sizeof msg, NULL, msg);
1324 weston_log("shader info: %s\n", msg);
1325 return GL_NONE;
1326 }
1327
1328 return s;
1329}
1330
1331static int
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03001332shader_init(struct gl_shader *shader, struct gl_renderer *renderer,
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001333 const char *vertex_source, const char *fragment_source)
1334{
1335 char msg[512];
1336 GLint status;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001337 int count;
1338 const char *sources[3];
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001339
1340 shader->vertex_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001341 compile_shader(GL_VERTEX_SHADER, 1, &vertex_source);
1342
1343 if (renderer->fragment_shader_debug) {
1344 sources[0] = fragment_source;
1345 sources[1] = fragment_debug;
1346 sources[2] = fragment_brace;
1347 count = 3;
1348 } else {
1349 sources[0] = fragment_source;
1350 sources[1] = fragment_brace;
1351 count = 2;
1352 }
1353
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001354 shader->fragment_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001355 compile_shader(GL_FRAGMENT_SHADER, count, sources);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001356
1357 shader->program = glCreateProgram();
1358 glAttachShader(shader->program, shader->vertex_shader);
1359 glAttachShader(shader->program, shader->fragment_shader);
1360 glBindAttribLocation(shader->program, 0, "position");
1361 glBindAttribLocation(shader->program, 1, "texcoord");
1362
1363 glLinkProgram(shader->program);
1364 glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
1365 if (!status) {
1366 glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
1367 weston_log("link info: %s\n", msg);
1368 return -1;
1369 }
1370
1371 shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
1372 shader->tex_uniforms[0] = glGetUniformLocation(shader->program, "tex");
1373 shader->tex_uniforms[1] = glGetUniformLocation(shader->program, "tex1");
1374 shader->tex_uniforms[2] = glGetUniformLocation(shader->program, "tex2");
1375 shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
1376 shader->color_uniform = glGetUniformLocation(shader->program, "color");
1377
1378 return 0;
1379}
1380
1381static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001382shader_release(struct gl_shader *shader)
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001383{
1384 glDeleteShader(shader->vertex_shader);
1385 glDeleteShader(shader->fragment_shader);
1386 glDeleteProgram(shader->program);
1387
1388 shader->vertex_shader = 0;
1389 shader->fragment_shader = 0;
1390 shader->program = 0;
1391}
1392
1393static void
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001394log_extensions(const char *name, const char *extensions)
1395{
1396 const char *p, *end;
1397 int l;
1398 int len;
1399
1400 l = weston_log("%s:", name);
1401 p = extensions;
1402 while (*p) {
1403 end = strchrnul(p, ' ');
1404 len = end - p;
1405 if (l + len > 78)
1406 l = weston_log_continue("\n" STAMP_SPACE "%.*s",
1407 len, p);
1408 else
1409 l += weston_log_continue(" %.*s", len, p);
1410 for (p = end; isspace(*p); p++)
1411 ;
1412 }
1413 weston_log_continue("\n");
1414}
1415
1416static void
1417log_egl_gl_info(EGLDisplay egldpy)
1418{
1419 const char *str;
1420
1421 str = eglQueryString(egldpy, EGL_VERSION);
1422 weston_log("EGL version: %s\n", str ? str : "(null)");
1423
1424 str = eglQueryString(egldpy, EGL_VENDOR);
1425 weston_log("EGL vendor: %s\n", str ? str : "(null)");
1426
1427 str = eglQueryString(egldpy, EGL_CLIENT_APIS);
1428 weston_log("EGL client APIs: %s\n", str ? str : "(null)");
1429
1430 str = eglQueryString(egldpy, EGL_EXTENSIONS);
1431 log_extensions("EGL extensions", str ? str : "(null)");
1432
1433 str = (char *)glGetString(GL_VERSION);
1434 weston_log("GL version: %s\n", str ? str : "(null)");
1435
1436 str = (char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
1437 weston_log("GLSL version: %s\n", str ? str : "(null)");
1438
1439 str = (char *)glGetString(GL_VENDOR);
1440 weston_log("GL vendor: %s\n", str ? str : "(null)");
1441
1442 str = (char *)glGetString(GL_RENDERER);
1443 weston_log("GL renderer: %s\n", str ? str : "(null)");
1444
1445 str = (char *)glGetString(GL_EXTENSIONS);
1446 log_extensions("GL extensions", str ? str : "(null)");
1447}
1448
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001449static void
1450log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
1451{
1452 EGLint r, g, b, a;
1453
1454 weston_log("Chosen EGL config details:\n");
1455
1456 weston_log_continue(STAMP_SPACE "RGBA bits");
1457 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_RED_SIZE, &r) &&
1458 eglGetConfigAttrib(egldpy, eglconfig, EGL_GREEN_SIZE, &g) &&
1459 eglGetConfigAttrib(egldpy, eglconfig, EGL_BLUE_SIZE, &b) &&
1460 eglGetConfigAttrib(egldpy, eglconfig, EGL_ALPHA_SIZE, &a))
1461 weston_log_continue(": %d %d %d %d\n", r, g, b, a);
1462 else
1463 weston_log_continue(" unknown\n");
1464
1465 weston_log_continue(STAMP_SPACE "swap interval range");
1466 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_MIN_SWAP_INTERVAL, &a) &&
1467 eglGetConfigAttrib(egldpy, eglconfig, EGL_MAX_SWAP_INTERVAL, &b))
1468 weston_log_continue(": %d - %d\n", a, b);
1469 else
1470 weston_log_continue(" unknown\n");
1471}
1472
John Kåre Alsaker44154502012-11-13 19:10:20 +01001473static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001474output_apply_border(struct weston_output *output, struct gl_renderer *gr)
John Kåre Alsaker44154502012-11-13 19:10:20 +01001475{
1476 output->border.top = gr->border.top;
1477 output->border.bottom = gr->border.bottom;
1478 output->border.left = gr->border.left;
1479 output->border.right = gr->border.right;
1480}
1481
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001482static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001483gl_renderer_set_border(struct weston_compositor *ec, int32_t width, int32_t height, void *data,
John Kåre Alsaker44154502012-11-13 19:10:20 +01001484 int32_t *edges)
1485{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001486 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker44154502012-11-13 19:10:20 +01001487 struct weston_output *output;
1488
1489 gr->border.left = edges[0];
1490 gr->border.right = edges[1];
1491 gr->border.top = edges[2];
1492 gr->border.bottom = edges[3];
1493
1494 gr->border.width = width;
1495 gr->border.height = height;
1496
1497 glGenTextures(1, &gr->border.texture);
1498 glBindTexture(GL_TEXTURE_2D, gr->border.texture);
1499 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1500 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1501 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1502 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1503
1504 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1505 width,
1506 height,
1507 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
1508 data);
1509
1510 wl_list_for_each(output, &ec->output_list, link)
1511 output_apply_border(output, gr);
1512}
1513
John Kåre Alsaker94659272012-11-13 19:10:18 +01001514static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001515gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001516
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001517static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001518gl_renderer_output_create(struct weston_output *output,
John Kåre Alsaker94659272012-11-13 19:10:18 +01001519 EGLNativeWindowType window)
1520{
1521 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001522 struct gl_renderer *gr = get_renderer(ec);
1523 struct gl_output_state *go = calloc(1, sizeof *go);
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001524 int i;
John Kåre Alsaker94659272012-11-13 19:10:18 +01001525
1526 if (!go)
1527 return -1;
1528
1529 go->egl_surface =
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001530 eglCreateWindowSurface(gr->egl_display,
1531 gr->egl_config,
John Kåre Alsaker94659272012-11-13 19:10:18 +01001532 window, NULL);
1533
1534 if (go->egl_surface == EGL_NO_SURFACE) {
1535 weston_log("failed to create egl surface\n");
1536 free(go);
1537 return -1;
1538 }
1539
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001540 if (gr->egl_context == NULL)
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001541 if (gl_renderer_setup(ec, go->egl_surface) < 0) {
John Kåre Alsaker94659272012-11-13 19:10:18 +01001542 free(go);
1543 return -1;
1544 }
1545
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001546 for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001547 pixman_region32_init(&go->buffer_damage[i]);
1548
John Kåre Alsaker94659272012-11-13 19:10:18 +01001549 output->renderer_state = go;
1550
John Kåre Alsaker44154502012-11-13 19:10:20 +01001551 output_apply_border(output, gr);
1552
John Kåre Alsaker94659272012-11-13 19:10:18 +01001553 return 0;
1554}
1555
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001556static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001557gl_renderer_output_destroy(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01001558{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001559 struct gl_renderer *gr = get_renderer(output->compositor);
1560 struct gl_output_state *go = get_output_state(output);
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001561 int i;
1562
1563 for (i = 0; i < 2; i++)
1564 pixman_region32_fini(&go->buffer_damage[i]);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001565
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001566 eglDestroySurface(gr->egl_display, go->egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001567
1568 free(go);
1569}
1570
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001571static EGLSurface
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001572gl_renderer_output_surface(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01001573{
1574 return get_output_state(output)->egl_surface;
1575}
1576
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03001577static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001578gl_renderer_destroy(struct weston_compositor *ec)
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001579{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001580 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001581
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001582 if (gr->has_bind_display)
1583 gr->unbind_display(gr->egl_display, ec->wl_display);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001584
1585 /* Work around crash in egl_dri2.c's dri2_make_current() - when does this apply? */
1586 eglMakeCurrent(gr->egl_display,
1587 EGL_NO_SURFACE, EGL_NO_SURFACE,
1588 EGL_NO_CONTEXT);
1589
1590 eglTerminate(gr->egl_display);
1591 eglReleaseThread();
Scott Moreau976a0502013-03-07 10:15:17 -07001592
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -04001593 wl_array_release(&gr->vertices);
1594 wl_array_release(&gr->indices);
1595 wl_array_release(&gr->vtxcnt);
1596
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +03001597 weston_binding_destroy(gr->fragment_binding);
1598 weston_binding_destroy(gr->fan_binding);
1599
Scott Moreau976a0502013-03-07 10:15:17 -07001600 free(gr);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001601}
1602
1603static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001604egl_choose_config(struct gl_renderer *gr, const EGLint *attribs,
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001605 const EGLint *visual_id)
1606{
1607 EGLint count = 0;
1608 EGLint matched = 0;
1609 EGLConfig *configs;
1610 int i;
1611
1612 if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1)
1613 return -1;
1614
1615 configs = calloc(count, sizeof *configs);
1616 if (!configs)
1617 return -1;
1618
1619 if (!eglChooseConfig(gr->egl_display, attribs, configs,
1620 count, &matched))
1621 goto out;
1622
1623 for (i = 0; i < matched; ++i) {
1624 EGLint id;
1625
1626 if (visual_id) {
1627 if (!eglGetConfigAttrib(gr->egl_display,
1628 configs[i], EGL_NATIVE_VISUAL_ID,
1629 &id))
1630 continue;
1631
Kristian Høgsbergc3ea26c2013-09-25 15:46:42 -07001632 if (id != 0 && id != *visual_id)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001633 continue;
1634 }
1635
1636 gr->egl_config = configs[i];
1637
1638 free(configs);
1639 return 0;
1640 }
1641
1642out:
1643 free(configs);
1644 return -1;
1645}
1646
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001647static const EGLint gl_renderer_opaque_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001648 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1649 EGL_RED_SIZE, 1,
1650 EGL_GREEN_SIZE, 1,
1651 EGL_BLUE_SIZE, 1,
1652 EGL_ALPHA_SIZE, 0,
1653 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1654 EGL_NONE
1655};
1656
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001657static const EGLint gl_renderer_alpha_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001658 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1659 EGL_RED_SIZE, 1,
1660 EGL_GREEN_SIZE, 1,
1661 EGL_BLUE_SIZE, 1,
1662 EGL_ALPHA_SIZE, 1,
1663 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1664 EGL_NONE
1665};
1666
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001667static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001668gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001669 const EGLint *attribs, const EGLint *visual_id)
1670{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001671 struct gl_renderer *gr;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001672 EGLint major, minor;
1673
1674 gr = calloc(1, sizeof *gr);
1675
1676 if (gr == NULL)
1677 return -1;
1678
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001679 gr->base.read_pixels = gl_renderer_read_pixels;
1680 gr->base.repaint_output = gl_renderer_repaint_output;
1681 gr->base.flush_damage = gl_renderer_flush_damage;
1682 gr->base.attach = gl_renderer_attach;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001683 gr->base.surface_set_color = gl_renderer_surface_set_color;
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03001684 gr->base.destroy = gl_renderer_destroy;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001685
1686 gr->egl_display = eglGetDisplay(display);
1687 if (gr->egl_display == EGL_NO_DISPLAY) {
1688 weston_log("failed to create display\n");
1689 goto err_egl;
1690 }
1691
1692 if (!eglInitialize(gr->egl_display, &major, &minor)) {
1693 weston_log("failed to initialize display\n");
1694 goto err_egl;
1695 }
1696
1697 if (egl_choose_config(gr, attribs, visual_id) < 0) {
1698 weston_log("failed to choose EGL config\n");
1699 goto err_egl;
1700 }
1701
1702 ec->renderer = &gr->base;
Pekka Paalanen7bb65102013-05-22 18:03:04 +03001703 ec->capabilities |= WESTON_CAP_ROTATION_ANY;
Pekka Paalanen4fc5dd02013-05-22 18:03:05 +03001704 ec->capabilities |= WESTON_CAP_CAPTURE_YFLIP;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001705
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001706 wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565);
1707
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001708 return 0;
1709
1710err_egl:
Pekka Paalanen326529f2012-11-27 12:25:25 +02001711 gl_renderer_print_egl_error_state();
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001712 free(gr);
1713 return -1;
1714}
1715
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001716static EGLDisplay
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001717gl_renderer_display(struct weston_compositor *ec)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001718{
1719 return get_renderer(ec)->egl_display;
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001720}
1721
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001722static int
1723compile_shaders(struct weston_compositor *ec)
1724{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001725 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker40684142012-11-13 19:10:25 +01001726
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03001727 gr->texture_shader_rgba.vertex_source = vertex_shader;
1728 gr->texture_shader_rgba.fragment_source = texture_fragment_shader_rgba;
1729
1730 gr->texture_shader_rgbx.vertex_source = vertex_shader;
1731 gr->texture_shader_rgbx.fragment_source = texture_fragment_shader_rgbx;
1732
1733 gr->texture_shader_egl_external.vertex_source = vertex_shader;
1734 gr->texture_shader_egl_external.fragment_source =
1735 texture_fragment_shader_egl_external;
1736
1737 gr->texture_shader_y_uv.vertex_source = vertex_shader;
1738 gr->texture_shader_y_uv.fragment_source = texture_fragment_shader_y_uv;
1739
1740 gr->texture_shader_y_u_v.vertex_source = vertex_shader;
1741 gr->texture_shader_y_u_v.fragment_source =
1742 texture_fragment_shader_y_u_v;
1743
1744 gr->texture_shader_y_u_v.vertex_source = vertex_shader;
1745 gr->texture_shader_y_xuxv.fragment_source =
1746 texture_fragment_shader_y_xuxv;
1747
1748 gr->solid_shader.vertex_source = vertex_shader;
1749 gr->solid_shader.fragment_source = solid_fragment_shader;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001750
1751 return 0;
1752}
1753
1754static void
Kristian Høgsberge3148752013-05-06 23:19:49 -04001755fragment_debug_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001756 void *data)
1757{
1758 struct weston_compositor *ec = data;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001759 struct gl_renderer *gr = get_renderer(ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001760 struct weston_output *output;
1761
John Kåre Alsaker40684142012-11-13 19:10:25 +01001762 gr->fragment_shader_debug ^= 1;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001763
John Kåre Alsaker40684142012-11-13 19:10:25 +01001764 shader_release(&gr->texture_shader_rgba);
1765 shader_release(&gr->texture_shader_rgbx);
1766 shader_release(&gr->texture_shader_egl_external);
1767 shader_release(&gr->texture_shader_y_uv);
1768 shader_release(&gr->texture_shader_y_u_v);
1769 shader_release(&gr->texture_shader_y_xuxv);
1770 shader_release(&gr->solid_shader);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001771
Ander Conselvan de Oliveira03fb4ef2012-12-03 17:08:11 +02001772 /* Force use_shader() to call glUseProgram(), since we need to use
1773 * the recompiled version of the shader. */
1774 gr->current_shader = NULL;
1775
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001776 wl_list_for_each(output, &ec->output_list, link)
1777 weston_output_damage(output);
1778}
1779
Kristian Høgsberg8799d412013-05-07 10:50:09 -04001780static void
1781fan_debug_repaint_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
1782 void *data)
1783{
1784 struct weston_compositor *compositor = data;
1785 struct gl_renderer *gr = get_renderer(compositor);
1786
1787 gr->fan_debug = !gr->fan_debug;
1788 weston_compositor_damage_all(compositor);
1789}
1790
John Kåre Alsaker94659272012-11-13 19:10:18 +01001791static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001792gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001793{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001794 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001795 const char *extensions;
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001796 EGLBoolean ret;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001797
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001798 static const EGLint context_attribs[] = {
1799 EGL_CONTEXT_CLIENT_VERSION, 2,
1800 EGL_NONE
1801 };
1802
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001803 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
1804 weston_log("failed to bind EGL_OPENGL_ES_API\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001805 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001806 return -1;
1807 }
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001808
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001809 log_egl_config_info(gr->egl_display, gr->egl_config);
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001810
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001811 gr->egl_context = eglCreateContext(gr->egl_display, gr->egl_config,
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001812 EGL_NO_CONTEXT, context_attribs);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001813 if (gr->egl_context == NULL) {
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001814 weston_log("failed to create context\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001815 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001816 return -1;
1817 }
1818
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001819 ret = eglMakeCurrent(gr->egl_display, egl_surface,
1820 egl_surface, gr->egl_context);
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001821 if (ret == EGL_FALSE) {
1822 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001823 gl_renderer_print_egl_error_state();
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001824 return -1;
1825 }
1826
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001827 log_egl_gl_info(gr->egl_display);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001828
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001829 gr->image_target_texture_2d =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001830 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001831 gr->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
1832 gr->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
1833 gr->bind_display =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001834 (void *) eglGetProcAddress("eglBindWaylandDisplayWL");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001835 gr->unbind_display =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001836 (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001837 gr->query_buffer =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001838 (void *) eglGetProcAddress("eglQueryWaylandBufferWL");
1839
1840 extensions = (const char *) glGetString(GL_EXTENSIONS);
1841 if (!extensions) {
1842 weston_log("Retrieving GL extension string failed.\n");
1843 return -1;
1844 }
1845
1846 if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
1847 weston_log("GL_EXT_texture_format_BGRA8888 not available\n");
1848 return -1;
1849 }
1850
1851 if (strstr(extensions, "GL_EXT_read_format_bgra"))
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01001852 ec->read_format = PIXMAN_a8r8g8b8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001853 else
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01001854 ec->read_format = PIXMAN_a8b8g8r8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001855
Kristian Høgsberg1c4f1632013-08-07 12:11:27 -07001856#ifdef GL_EXT_unpack_subimage
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001857 if (strstr(extensions, "GL_EXT_unpack_subimage"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001858 gr->has_unpack_subimage = 1;
Kristian Høgsberg1c4f1632013-08-07 12:11:27 -07001859#endif
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001860
1861 if (strstr(extensions, "GL_OES_EGL_image_external"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001862 gr->has_egl_image_external = 1;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001863
1864 extensions =
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001865 (const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001866 if (!extensions) {
1867 weston_log("Retrieving EGL extension string failed.\n");
1868 return -1;
1869 }
1870
1871 if (strstr(extensions, "EGL_WL_bind_wayland_display"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001872 gr->has_bind_display = 1;
1873 if (gr->has_bind_display) {
1874 ret = gr->bind_display(gr->egl_display, ec->wl_display);
Pekka Paalanen035a0322012-10-24 09:43:06 +03001875 if (!ret)
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001876 gr->has_bind_display = 0;
Pekka Paalanen035a0322012-10-24 09:43:06 +03001877 }
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001878
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001879 if (strstr(extensions, "EGL_EXT_buffer_age"))
1880 gr->has_egl_buffer_age = 1;
1881 else
1882 weston_log("warning: EGL_EXT_buffer_age not supported. "
1883 "Performance could be affected.\n");
1884
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001885 glActiveTexture(GL_TEXTURE0);
1886
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001887 if (compile_shaders(ec))
1888 return -1;
1889
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +03001890 gr->fragment_binding =
1891 weston_compositor_add_debug_binding(ec, KEY_S,
1892 fragment_debug_binding,
1893 ec);
1894 gr->fan_binding =
1895 weston_compositor_add_debug_binding(ec, KEY_F,
1896 fan_debug_repaint_binding,
1897 ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001898
Pekka Paalanen035a0322012-10-24 09:43:06 +03001899 weston_log("GL ES 2 renderer features:\n");
1900 weston_log_continue(STAMP_SPACE "read-back format: %s\n",
Pekka Paalanenfe4eacf2013-01-10 16:50:42 +02001901 ec->read_format == PIXMAN_a8r8g8b8 ? "BGRA" : "RGBA");
Pekka Paalanen035a0322012-10-24 09:43:06 +03001902 weston_log_continue(STAMP_SPACE "wl_shm sub-image to texture: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001903 gr->has_unpack_subimage ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03001904 weston_log_continue(STAMP_SPACE "EGL Wayland extension: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001905 gr->has_bind_display ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03001906
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001907
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001908 return 0;
1909}
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001910
1911WL_EXPORT struct gl_renderer_interface gl_renderer_interface = {
1912 .opaque_attribs = gl_renderer_opaque_attribs,
1913 .alpha_attribs = gl_renderer_alpha_attribs,
1914
1915 .create = gl_renderer_create,
1916 .display = gl_renderer_display,
1917 .output_create = gl_renderer_output_create,
1918 .output_destroy = gl_renderer_output_destroy,
1919 .output_surface = gl_renderer_output_surface,
1920 .set_border = gl_renderer_set_border,
1921 .print_egl_error_state = gl_renderer_print_egl_error_state
1922};