blob: 9738623112bd73fa60d81ebf2755f53ce43a8d51 [file] [log] [blame]
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001/*
2 * Copyright © 2012 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
Daniel Stonec228e232013-05-22 18:03:19 +030023#include "config.h"
Kristian Høgsberg25894fc2012-09-05 22:06:26 -040024
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010025#include <GLES2/gl2.h>
26#include <GLES2/gl2ext.h>
27
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -040028#include <stdlib.h>
Kristian Høgsberg25894fc2012-09-05 22:06:26 -040029#include <string.h>
30#include <ctype.h>
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +030031#include <float.h>
32#include <assert.h>
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +020033#include <linux/input.h>
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -040034
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010035#include "gl-renderer.h"
Sam Spilsbury619859c2013-09-13 10:01:21 +080036#include "vertex-clipping.h"
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010037
38#include <EGL/eglext.h>
39#include "weston-egl-ext.h"
Kristian Høgsbergd7c17262012-09-05 21:54:15 -040040
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010041struct gl_shader {
John Kåre Alsaker40684142012-11-13 19:10:25 +010042 GLuint program;
43 GLuint vertex_shader, fragment_shader;
44 GLint proj_uniform;
45 GLint tex_uniforms[3];
46 GLint alpha_uniform;
47 GLint color_uniform;
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +030048 const char *vertex_source, *fragment_source;
John Kåre Alsaker40684142012-11-13 19:10:25 +010049};
50
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +020051#define BUFFER_DAMAGE_COUNT 2
52
Jason Ekstrand0b61bf42013-10-27 22:24:54 -050053struct gl_border_image {
54 GLuint tex;
55 int32_t width, height;
56 int32_t tex_width;
57 int dirty;
58 void *data;
59};
60
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010061struct gl_output_state {
John Kåre Alsaker94659272012-11-13 19:10:18 +010062 EGLSurface egl_surface;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +020063 pixman_region32_t buffer_damage[BUFFER_DAMAGE_COUNT];
Jason Ekstrand0b61bf42013-10-27 22:24:54 -050064 struct gl_border_image borders[4];
John Kåre Alsaker94659272012-11-13 19:10:18 +010065};
66
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +030067enum buffer_type {
68 BUFFER_TYPE_NULL,
69 BUFFER_TYPE_SHM,
70 BUFFER_TYPE_EGL
71};
72
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010073struct gl_surface_state {
John Kåre Alsaker878f4492012-11-13 19:10:23 +010074 GLfloat color[4];
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010075 struct gl_shader *shader;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +010076
77 GLuint textures[3];
78 int num_textures;
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +030079 int needs_full_upload;
Pekka Paalanen81ee3f52012-12-04 15:58:16 +020080 pixman_region32_t texture_damage;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +010081
82 EGLImageKHR images[3];
83 GLenum target;
84 int num_images;
Pekka Paalanenfb003d32012-12-04 15:58:13 +020085
86 struct weston_buffer_reference buffer_ref;
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +030087 enum buffer_type buffer_type;
Pekka Paalanen68033ac2012-12-04 15:58:15 +020088 int pitch; /* in pixels */
Alexander Larsson4ea95522013-05-22 14:41:37 +020089 int height; /* in pixels */
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +040090 int y_inverted;
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +030091
92 struct weston_surface *surface;
93
94 struct wl_listener surface_destroy_listener;
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +030095 struct wl_listener renderer_destroy_listener;
John Kåre Alsaker878f4492012-11-13 19:10:23 +010096};
97
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010098struct gl_renderer {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +010099 struct weston_renderer base;
100 int fragment_shader_debug;
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400101 int fan_debug;
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +0300102 struct weston_binding *fragment_binding;
103 struct weston_binding *fan_binding;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100104
105 EGLDisplay egl_display;
106 EGLContext egl_context;
107 EGLConfig egl_config;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100108
109 struct {
110 int32_t top, bottom, left, right;
111 GLuint texture;
112 int32_t width, height;
113 } border;
John Kåre Alsaker40684142012-11-13 19:10:25 +0100114
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400115 struct wl_array vertices;
116 struct wl_array indices; /* only used in compositor-wayland */
117 struct wl_array vtxcnt;
118
John Kåre Alsaker320711d2012-11-13 19:10:27 +0100119 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
120 PFNEGLCREATEIMAGEKHRPROC create_image;
121 PFNEGLDESTROYIMAGEKHRPROC destroy_image;
122
123 int has_unpack_subimage;
124
125 PFNEGLBINDWAYLANDDISPLAYWL bind_display;
126 PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
127 PFNEGLQUERYWAYLANDBUFFERWL query_buffer;
128 int has_bind_display;
129
130 int has_egl_image_external;
131
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200132 int has_egl_buffer_age;
133
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100134 struct gl_shader texture_shader_rgba;
135 struct gl_shader texture_shader_rgbx;
136 struct gl_shader texture_shader_egl_external;
137 struct gl_shader texture_shader_y_uv;
138 struct gl_shader texture_shader_y_u_v;
139 struct gl_shader texture_shader_y_xuxv;
140 struct gl_shader invert_color_shader;
141 struct gl_shader solid_shader;
142 struct gl_shader *current_shader;
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +0300143
144 struct wl_signal destroy_signal;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100145};
John Kåre Alsaker94659272012-11-13 19:10:18 +0100146
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100147static inline struct gl_output_state *
John Kåre Alsaker94659272012-11-13 19:10:18 +0100148get_output_state(struct weston_output *output)
149{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100150 return (struct gl_output_state *)output->renderer_state;
John Kåre Alsaker94659272012-11-13 19:10:18 +0100151}
152
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300153static int
154gl_renderer_create_surface(struct weston_surface *surface);
155
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100156static inline struct gl_surface_state *
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100157get_surface_state(struct weston_surface *surface)
158{
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300159 if (!surface->renderer_state)
160 gl_renderer_create_surface(surface);
161
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100162 return (struct gl_surface_state *)surface->renderer_state;
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100163}
164
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100165static inline struct gl_renderer *
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100166get_renderer(struct weston_compositor *ec)
167{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100168 return (struct gl_renderer *)ec->renderer;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100169}
170
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400171static const char *
172egl_error_string(EGLint code)
173{
174#define MYERRCODE(x) case x: return #x;
175 switch (code) {
176 MYERRCODE(EGL_SUCCESS)
177 MYERRCODE(EGL_NOT_INITIALIZED)
178 MYERRCODE(EGL_BAD_ACCESS)
179 MYERRCODE(EGL_BAD_ALLOC)
180 MYERRCODE(EGL_BAD_ATTRIBUTE)
181 MYERRCODE(EGL_BAD_CONTEXT)
182 MYERRCODE(EGL_BAD_CONFIG)
183 MYERRCODE(EGL_BAD_CURRENT_SURFACE)
184 MYERRCODE(EGL_BAD_DISPLAY)
185 MYERRCODE(EGL_BAD_SURFACE)
186 MYERRCODE(EGL_BAD_MATCH)
187 MYERRCODE(EGL_BAD_PARAMETER)
188 MYERRCODE(EGL_BAD_NATIVE_PIXMAP)
189 MYERRCODE(EGL_BAD_NATIVE_WINDOW)
190 MYERRCODE(EGL_CONTEXT_LOST)
191 default:
192 return "unknown";
193 }
194#undef MYERRCODE
195}
196
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +0300197static void
Pekka Paalanen326529f2012-11-27 12:25:25 +0200198gl_renderer_print_egl_error_state(void)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400199{
200 EGLint code;
201
202 code = eglGetError();
203 weston_log("EGL error state: %s (0x%04lx)\n",
204 egl_error_string(code), (long)code);
205}
206
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400207#define max(a, b) (((a) > (b)) ? (a) : (b))
208#define min(a, b) (((a) > (b)) ? (b) : (a))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400209
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300210/*
211 * Compute the boundary vertices of the intersection of the global coordinate
212 * aligned rectangle 'rect', and an arbitrary quadrilateral produced from
213 * 'surf_rect' when transformed from surface coordinates into global coordinates.
214 * The vertices are written to 'ex' and 'ey', and the return value is the
215 * number of vertices. Vertices are produced in clockwise winding order.
216 * Guarantees to produce either zero vertices, or 3-8 vertices with non-zero
217 * polygon area.
218 */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400219static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500220calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400221 pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
222{
Sam Spilsbury619859c2013-09-13 10:01:21 +0800223
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300224 struct clip_context ctx;
225 int i, n;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400226 GLfloat min_x, max_x, min_y, max_y;
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300227 struct polygon8 surf = {
228 { surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1 },
229 { surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2 },
230 4
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400231 };
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400232
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300233 ctx.clip.x1 = rect->x1;
234 ctx.clip.y1 = rect->y1;
235 ctx.clip.x2 = rect->x2;
236 ctx.clip.y2 = rect->y2;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400237
238 /* transform surface to screen space: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300239 for (i = 0; i < surf.n; i++)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500240 weston_view_to_global_float(ev, surf.x[i], surf.y[i],
241 &surf.x[i], &surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400242
243 /* find bounding box: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300244 min_x = max_x = surf.x[0];
245 min_y = max_y = surf.y[0];
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400246
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300247 for (i = 1; i < surf.n; i++) {
248 min_x = min(min_x, surf.x[i]);
249 max_x = max(max_x, surf.x[i]);
250 min_y = min(min_y, surf.y[i]);
251 max_y = max(max_y, surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400252 }
253
254 /* First, simple bounding box check to discard early transformed
255 * surface rects that do not intersect with the clip region:
256 */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300257 if ((min_x >= ctx.clip.x2) || (max_x <= ctx.clip.x1) ||
258 (min_y >= ctx.clip.y2) || (max_y <= ctx.clip.y1))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400259 return 0;
260
261 /* Simple case, bounding box edges are parallel to surface edges,
262 * there will be only four edges. We just need to clip the surface
263 * vertices to the clip rect bounds:
264 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500265 if (!ev->transform.enabled)
Sam Spilsbury619859c2013-09-13 10:01:21 +0800266 return clip_simple(&ctx, &surf, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400267
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300268 /* Transformed case: use a general polygon clipping algorithm to
269 * clip the surface rectangle with each side of 'rect'.
270 * The algorithm is Sutherland-Hodgman, as explained in
271 * http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm
272 * but without looking at any of that code.
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400273 */
Sam Spilsbury619859c2013-09-13 10:01:21 +0800274 n = clip_transformed(&ctx, &surf, ex, ey);
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300275
276 if (n < 3)
277 return 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400278
279 return n;
280}
281
282static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500283texture_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400284 pixman_region32_t *surf_region)
285{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500286 struct gl_surface_state *gs = get_surface_state(ev->surface);
287 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400288 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400289 GLfloat *v, inv_width, inv_height;
290 unsigned int *vtxcnt, nvtx = 0;
291 pixman_box32_t *rects, *surf_rects;
292 int i, j, k, nrects, nsurf;
293
294 rects = pixman_region32_rectangles(region, &nrects);
295 surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
296
297 /* worst case we can have 8 vertices per rect (ie. clipped into
298 * an octagon):
299 */
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400300 v = wl_array_add(&gr->vertices, nrects * nsurf * 8 * 4 * sizeof *v);
301 vtxcnt = wl_array_add(&gr->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400302
Pekka Paalanen68033ac2012-12-04 15:58:15 +0200303 inv_width = 1.0 / gs->pitch;
Alexander Larsson4ea95522013-05-22 14:41:37 +0200304 inv_height = 1.0 / gs->height;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400305
306 for (i = 0; i < nrects; i++) {
307 pixman_box32_t *rect = &rects[i];
308 for (j = 0; j < nsurf; j++) {
309 pixman_box32_t *surf_rect = &surf_rects[j];
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200310 GLfloat sx, sy, bx, by;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400311 GLfloat ex[8], ey[8]; /* edge points in screen space */
312 int n;
313
314 /* The transformed surface, after clipping to the clip region,
315 * can have as many as eight sides, emitted as a triangle-fan.
316 * The first vertex in the triangle fan can be chosen arbitrarily,
317 * since the area is guaranteed to be convex.
318 *
319 * If a corner of the transformed surface falls outside of the
320 * clip region, instead of emitting one vertex for the corner
321 * of the surface, up to two are emitted for two corresponding
322 * intersection point(s) between the surface and the clip region.
323 *
324 * To do this, we first calculate the (up to eight) points that
325 * form the intersection of the clip rect and the transformed
326 * surface.
327 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500328 n = calculate_edges(ev, rect, surf_rect, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400329 if (n < 3)
330 continue;
331
332 /* emit edge points: */
333 for (k = 0; k < n; k++) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500334 weston_view_from_global_float(ev, ex[k], ey[k],
335 &sx, &sy);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400336 /* position: */
337 *(v++) = ex[k];
338 *(v++) = ey[k];
339 /* texcoord: */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500340 weston_surface_to_buffer_float(ev->surface,
341 sx, sy,
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200342 &bx, &by);
343 *(v++) = bx * inv_width;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +0400344 if (gs->y_inverted) {
345 *(v++) = by * inv_height;
346 } else {
347 *(v++) = (gs->height - by) * inv_height;
348 }
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400349 }
350
351 vtxcnt[nvtx++] = n;
352 }
353 }
354
355 return nvtx;
356}
357
358static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500359triangle_fan_debug(struct weston_view *view, int first, int count)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400360{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500361 struct weston_compositor *compositor = view->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100362 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400363 int i;
364 GLushort *buffer;
365 GLushort *index;
366 int nelems;
367 static int color_idx = 0;
368 static const GLfloat color[][4] = {
369 { 1.0, 0.0, 0.0, 1.0 },
370 { 0.0, 1.0, 0.0, 1.0 },
371 { 0.0, 0.0, 1.0, 1.0 },
372 { 1.0, 1.0, 1.0, 1.0 },
373 };
374
375 nelems = (count - 1 + count - 2) * 2;
376
377 buffer = malloc(sizeof(GLushort) * nelems);
378 index = buffer;
379
380 for (i = 1; i < count; i++) {
381 *index++ = first;
382 *index++ = first + i;
383 }
384
385 for (i = 2; i < count; i++) {
386 *index++ = first + i - 1;
387 *index++ = first + i;
388 }
389
John Kåre Alsaker40684142012-11-13 19:10:25 +0100390 glUseProgram(gr->solid_shader.program);
391 glUniform4fv(gr->solid_shader.color_uniform, 1,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400392 color[color_idx++ % ARRAY_LENGTH(color)]);
393 glDrawElements(GL_LINES, nelems, GL_UNSIGNED_SHORT, buffer);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100394 glUseProgram(gr->current_shader->program);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400395 free(buffer);
396}
397
398static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500399repaint_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400400 pixman_region32_t *surf_region)
401{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500402 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400403 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400404 GLfloat *v;
405 unsigned int *vtxcnt;
406 int i, first, nfans;
407
408 /* The final region to be painted is the intersection of
409 * 'region' and 'surf_region'. However, 'region' is in the global
410 * coordinates, and 'surf_region' is in the surface-local
411 * coordinates. texture_region() will iterate over all pairs of
412 * rectangles from both regions, compute the intersection
413 * polygon for each pair, and store it as a triangle fan if
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400414 * it has a non-zero area (at least 3 vertices1, actually).
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400415 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500416 nfans = texture_region(ev, region, surf_region);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400417
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400418 v = gr->vertices.data;
419 vtxcnt = gr->vtxcnt.data;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400420
421 /* position: */
422 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
423 glEnableVertexAttribArray(0);
424
425 /* texcoord: */
426 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
427 glEnableVertexAttribArray(1);
428
429 for (i = 0, first = 0; i < nfans; i++) {
430 glDrawArrays(GL_TRIANGLE_FAN, first, vtxcnt[i]);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400431 if (gr->fan_debug)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500432 triangle_fan_debug(ev, first, vtxcnt[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400433 first += vtxcnt[i];
434 }
435
436 glDisableVertexAttribArray(1);
437 glDisableVertexAttribArray(0);
438
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400439 gr->vertices.size = 0;
440 gr->vtxcnt.size = 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400441}
442
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100443static int
444use_output(struct weston_output *output)
445{
446 static int errored;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100447 struct gl_output_state *go = get_output_state(output);
448 struct gl_renderer *gr = get_renderer(output->compositor);
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100449 EGLBoolean ret;
450
451 ret = eglMakeCurrent(gr->egl_display, go->egl_surface,
452 go->egl_surface, gr->egl_context);
453
454 if (ret == EGL_FALSE) {
455 if (errored)
456 return -1;
457 errored = 1;
458 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +0200459 gl_renderer_print_egl_error_state();
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100460 return -1;
461 }
462
463 return 0;
464}
465
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300466static int
467shader_init(struct gl_shader *shader, struct gl_renderer *gr,
468 const char *vertex_source, const char *fragment_source);
469
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400470static void
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300471use_shader(struct gl_renderer *gr, struct gl_shader *shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400472{
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300473 if (!shader->program) {
474 int ret;
475
476 ret = shader_init(shader, gr,
477 shader->vertex_source,
478 shader->fragment_source);
479
480 if (ret < 0)
481 weston_log("warning: failed to compile shader\n");
482 }
483
John Kåre Alsaker40684142012-11-13 19:10:25 +0100484 if (gr->current_shader == shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400485 return;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400486 glUseProgram(shader->program);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100487 gr->current_shader = shader;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400488}
489
490static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100491shader_uniforms(struct gl_shader *shader,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500492 struct weston_view *view,
493 struct weston_output *output)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400494{
495 int i;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500496 struct gl_surface_state *gs = get_surface_state(view->surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400497
498 glUniformMatrix4fv(shader->proj_uniform,
499 1, GL_FALSE, output->matrix.d);
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100500 glUniform4fv(shader->color_uniform, 1, gs->color);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500501 glUniform1f(shader->alpha_uniform, view->alpha);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400502
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100503 for (i = 0; i < gs->num_textures; i++)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400504 glUniform1i(shader->tex_uniforms[i], i);
505}
506
507static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500508draw_view(struct weston_view *ev, struct weston_output *output,
509 pixman_region32_t *damage) /* in global coordinates */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400510{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500511 struct weston_compositor *ec = ev->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100512 struct gl_renderer *gr = get_renderer(ec);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500513 struct gl_surface_state *gs = get_surface_state(ev->surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400514 /* repaint bounding region in global coordinates: */
515 pixman_region32_t repaint;
516 /* non-opaque region in surface coordinates: */
517 pixman_region32_t surface_blend;
518 GLint filter;
519 int i;
520
521 pixman_region32_init(&repaint);
522 pixman_region32_intersect(&repaint,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500523 &ev->transform.boundingbox, damage);
524 pixman_region32_subtract(&repaint, &repaint, &ev->clip);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400525
526 if (!pixman_region32_not_empty(&repaint))
527 goto out;
528
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400529 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
530
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400531 if (gr->fan_debug) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100532 use_shader(gr, &gr->solid_shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500533 shader_uniforms(&gr->solid_shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400534 }
535
John Kåre Alsaker40684142012-11-13 19:10:25 +0100536 use_shader(gr, gs->shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500537 shader_uniforms(gs->shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400538
Jason Ekstranda7af7042013-10-12 22:38:11 -0500539 if (ev->transform.enabled || output->zoom.active ||
540 output->current_scale != ev->surface->buffer_scale)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400541 filter = GL_LINEAR;
542 else
543 filter = GL_NEAREST;
544
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100545 for (i = 0; i < gs->num_textures; i++) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400546 glActiveTexture(GL_TEXTURE0 + i);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100547 glBindTexture(gs->target, gs->textures[i]);
548 glTexParameteri(gs->target, GL_TEXTURE_MIN_FILTER, filter);
549 glTexParameteri(gs->target, GL_TEXTURE_MAG_FILTER, filter);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400550 }
551
552 /* blended region is whole surface minus opaque region: */
553 pixman_region32_init_rect(&surface_blend, 0, 0,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500554 ev->geometry.width, ev->geometry.height);
555 pixman_region32_subtract(&surface_blend, &surface_blend, &ev->surface->opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400556
Jason Ekstranda7af7042013-10-12 22:38:11 -0500557 /* XXX: Should we be using ev->transform.opaque here? */
558 if (pixman_region32_not_empty(&ev->surface->opaque)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100559 if (gs->shader == &gr->texture_shader_rgba) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400560 /* Special case for RGBA textures with possibly
561 * bad data in alpha channel: use the shader
562 * that forces texture alpha = 1.0.
563 * Xwayland surfaces need this.
564 */
John Kåre Alsaker40684142012-11-13 19:10:25 +0100565 use_shader(gr, &gr->texture_shader_rgbx);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500566 shader_uniforms(&gr->texture_shader_rgbx, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400567 }
568
Jason Ekstranda7af7042013-10-12 22:38:11 -0500569 if (ev->alpha < 1.0)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400570 glEnable(GL_BLEND);
571 else
572 glDisable(GL_BLEND);
573
Jason Ekstranda7af7042013-10-12 22:38:11 -0500574 repaint_region(ev, &repaint, &ev->surface->opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400575 }
576
577 if (pixman_region32_not_empty(&surface_blend)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100578 use_shader(gr, gs->shader);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400579 glEnable(GL_BLEND);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500580 repaint_region(ev, &repaint, &surface_blend);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400581 }
582
583 pixman_region32_fini(&surface_blend);
584
585out:
586 pixman_region32_fini(&repaint);
587}
588
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400589static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500590repaint_views(struct weston_output *output, pixman_region32_t *damage)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400591{
592 struct weston_compositor *compositor = output->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500593 struct weston_view *view;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400594
Jason Ekstranda7af7042013-10-12 22:38:11 -0500595 wl_list_for_each_reverse(view, &compositor->view_list, link)
596 if (view->plane == &compositor->primary_plane)
597 draw_view(view, output, damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400598}
599
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500600static void
601draw_output_border_texture(struct gl_border_image *img, int32_t x, int32_t y,
602 int32_t width, int32_t height)
603{
604 static GLushort indices [] = { 0, 1, 3, 3, 1, 2 };
605
606 if (!img->data) {
607 if (img->tex) {
608 glDeleteTextures(1, &img->tex);
609 img->tex = 0;
610 }
611
612 return;
613 }
614
615 if (!img->tex) {
616 glGenTextures(1, &img->tex);
617 glBindTexture(GL_TEXTURE_2D, img->tex);
618
619 glTexParameteri(GL_TEXTURE_2D,
620 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
621 glTexParameteri(GL_TEXTURE_2D,
622 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
623 glTexParameteri(GL_TEXTURE_2D,
624 GL_TEXTURE_MIN_FILTER, GL_NEAREST);
625 glTexParameteri(GL_TEXTURE_2D,
626 GL_TEXTURE_MAG_FILTER, GL_NEAREST);
627 } else {
628 glBindTexture(GL_TEXTURE_2D, img->tex);
629 }
630
631 if (img->dirty) {
632#ifdef GL_EXT_unpack_subimage
633 glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0);
634 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
635 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
636#endif
637 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
638 img->tex_width, img->height, 0,
639 GL_BGRA_EXT, GL_UNSIGNED_BYTE, img->data);
640 img->dirty = 0;
641 }
642
643 GLfloat texcoord[] = {
644 0.0f, 0.0f,
645 (GLfloat)img->width / (GLfloat)img->tex_width, 0.0f,
646 (GLfloat)img->width / (GLfloat)img->tex_width, 1.0f,
647 0.0f, 1.0f,
648 };
649
650 GLfloat verts[] = {
651 x, y,
652 x + width, y,
653 x + width, y + height,
654 x, y + height
655 };
656
657 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
658 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord);
659 glEnableVertexAttribArray(0);
660 glEnableVertexAttribArray(1);
661
662 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
663
664 glDisableVertexAttribArray(1);
665 glDisableVertexAttribArray(0);
666}
667
668static void
669draw_output_border(struct weston_output *output)
670{
671 struct gl_output_state *go = get_output_state(output);
672 struct gl_renderer *gr = get_renderer(output->compositor);
673 struct gl_shader *shader = &gr->texture_shader_rgba;
674 int32_t full_width;
675
676 glDisable(GL_BLEND);
677 use_shader(gr, shader);
678
679 glUniformMatrix4fv(shader->proj_uniform,
680 1, GL_FALSE, output->matrix.d);
681
682 glUniform1i(shader->tex_uniforms[0], 0);
683 glUniform1f(shader->alpha_uniform, 1);
684 glActiveTexture(GL_TEXTURE0);
685
686 full_width = output->width + output->border.left + output->border.right;
687 draw_output_border_texture(&go->borders[GL_RENDERER_BORDER_TOP],
688 -output->border.left, -output->border.top,
689 full_width, output->border.top);
690 draw_output_border_texture(&go->borders[GL_RENDERER_BORDER_LEFT],
691 -output->border.left, 0,
692 output->border.left, output->height);
693 draw_output_border_texture(&go->borders[GL_RENDERER_BORDER_RIGHT],
694 output->width, 0,
695 output->border.right, output->height);
696 draw_output_border_texture(&go->borders[GL_RENDERER_BORDER_BOTTOM],
697 -output->border.left, output->height,
698 full_width, output->border.bottom);
699}
John Kåre Alsaker44154502012-11-13 19:10:20 +0100700
701static int
702texture_border(struct weston_output *output)
703{
704 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100705 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100706 GLfloat *d;
Kristian Høgsberg73db9242013-08-28 23:05:29 -0700707 unsigned short *p;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100708 int i, j, k, n;
709 GLfloat x[4], y[4], u[4], v[4];
710
711 x[0] = -gr->border.left;
712 x[1] = 0;
Hardeningff39efa2013-09-18 23:56:35 +0200713 x[2] = output->current_mode->width;
714 x[3] = output->current_mode->width + gr->border.right;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100715
716 y[0] = -gr->border.top;
717 y[1] = 0;
Hardeningff39efa2013-09-18 23:56:35 +0200718 y[2] = output->current_mode->height;
719 y[3] = output->current_mode->height + gr->border.bottom;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100720
721 u[0] = 0.0;
722 u[1] = (GLfloat) gr->border.left / gr->border.width;
723 u[2] = (GLfloat) (gr->border.width - gr->border.right) / gr->border.width;
724 u[3] = 1.0;
725
726 v[0] = 0.0;
727 v[1] = (GLfloat) gr->border.top / gr->border.height;
728 v[2] = (GLfloat) (gr->border.height - gr->border.bottom) / gr->border.height;
729 v[3] = 1.0;
730
731 n = 8;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400732 d = wl_array_add(&gr->vertices, n * 16 * sizeof *d);
733 p = wl_array_add(&gr->indices, n * 6 * sizeof *p);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100734
735 k = 0;
736 for (i = 0; i < 3; i++)
737 for (j = 0; j < 3; j++) {
738
739 if (i == 1 && j == 1)
740 continue;
741
742 d[ 0] = x[i];
743 d[ 1] = y[j];
744 d[ 2] = u[i];
745 d[ 3] = v[j];
746
747 d[ 4] = x[i];
748 d[ 5] = y[j + 1];
749 d[ 6] = u[i];
750 d[ 7] = v[j + 1];
751
752 d[ 8] = x[i + 1];
753 d[ 9] = y[j];
754 d[10] = u[i + 1];
755 d[11] = v[j];
756
757 d[12] = x[i + 1];
758 d[13] = y[j + 1];
759 d[14] = u[i + 1];
760 d[15] = v[j + 1];
761
762 p[0] = k + 0;
763 p[1] = k + 1;
764 p[2] = k + 2;
765 p[3] = k + 2;
766 p[4] = k + 1;
767 p[5] = k + 3;
768
769 d += 16;
770 p += 6;
771 k += 4;
772 }
773
774 return k / 4;
775}
776
777static void
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500778draw_global_border(struct weston_output *output)
John Kåre Alsaker44154502012-11-13 19:10:20 +0100779{
780 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100781 struct gl_renderer *gr = get_renderer(ec);
782 struct gl_shader *shader = &gr->texture_shader_rgba;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100783 GLfloat *v;
784 int n;
785
786 glDisable(GL_BLEND);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100787 use_shader(gr, shader);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100788
789 glUniformMatrix4fv(shader->proj_uniform,
790 1, GL_FALSE, output->matrix.d);
791
792 glUniform1i(shader->tex_uniforms[0], 0);
793 glUniform1f(shader->alpha_uniform, 1);
794
795 n = texture_border(output);
796
797 glActiveTexture(GL_TEXTURE0);
798 glBindTexture(GL_TEXTURE_2D, gr->border.texture);
799
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400800 v = gr->vertices.data;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100801 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
802 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
803 glEnableVertexAttribArray(0);
804 glEnableVertexAttribArray(1);
805
806 glDrawElements(GL_TRIANGLES, n * 6,
Kristian Høgsberg73db9242013-08-28 23:05:29 -0700807 GL_UNSIGNED_SHORT, gr->indices.data);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100808
809 glDisableVertexAttribArray(1);
810 glDisableVertexAttribArray(0);
811
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400812 gr->vertices.size = 0;
813 gr->indices.size = 0;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100814}
815
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400816static void
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200817output_get_buffer_damage(struct weston_output *output,
818 pixman_region32_t *buffer_damage)
819{
820 struct gl_output_state *go = get_output_state(output);
821 struct gl_renderer *gr = get_renderer(output->compositor);
822 EGLint buffer_age = 0;
823 EGLBoolean ret;
824 int i;
825
826 if (gr->has_egl_buffer_age) {
827 ret = eglQuerySurface(gr->egl_display, go->egl_surface,
828 EGL_BUFFER_AGE_EXT, &buffer_age);
829 if (ret == EGL_FALSE) {
830 weston_log("buffer age query failed.\n");
831 gl_renderer_print_egl_error_state();
832 }
833 }
834
835 if (buffer_age == 0 || buffer_age - 1 > BUFFER_DAMAGE_COUNT)
836 pixman_region32_copy(buffer_damage, &output->region);
837 else
838 for (i = 0; i < buffer_age - 1; i++)
839 pixman_region32_union(buffer_damage, buffer_damage,
840 &go->buffer_damage[i]);
841}
842
843static void
844output_rotate_damage(struct weston_output *output,
845 pixman_region32_t *output_damage)
846{
847 struct gl_output_state *go = get_output_state(output);
848 struct gl_renderer *gr = get_renderer(output->compositor);
849 int i;
850
851 if (!gr->has_egl_buffer_age)
852 return;
853
854 for (i = BUFFER_DAMAGE_COUNT - 1; i >= 1; i--)
855 pixman_region32_copy(&go->buffer_damage[i],
856 &go->buffer_damage[i - 1]);
857
858 pixman_region32_copy(&go->buffer_damage[0], output_damage);
859}
860
861static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100862gl_renderer_repaint_output(struct weston_output *output,
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400863 pixman_region32_t *output_damage)
864{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100865 struct gl_output_state *go = get_output_state(output);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400866 struct weston_compositor *compositor = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100867 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400868 EGLBoolean ret;
869 static int errored;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200870 int32_t width, height;
871 pixman_region32_t buffer_damage, total_damage;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400872
Hardeningff39efa2013-09-18 23:56:35 +0200873 width = output->current_mode->width +
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400874 output->border.left + output->border.right;
Hardeningff39efa2013-09-18 23:56:35 +0200875 height = output->current_mode->height +
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400876 output->border.top + output->border.bottom;
877
878 glViewport(0, 0, width, height);
879
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100880 if (use_output(output) < 0)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400881 return;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400882
883 /* if debugging, redraw everything outside the damage to clean up
884 * debug lines from the previous draw on this buffer:
885 */
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400886 if (gr->fan_debug) {
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400887 pixman_region32_t undamaged;
888 pixman_region32_init(&undamaged);
889 pixman_region32_subtract(&undamaged, &output->region,
890 output_damage);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400891 gr->fan_debug = 0;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500892 repaint_views(output, &undamaged);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400893 gr->fan_debug = 1;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400894 pixman_region32_fini(&undamaged);
895 }
896
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +0200897 pixman_region32_init(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200898 pixman_region32_init(&buffer_damage);
899
900 output_get_buffer_damage(output, &buffer_damage);
901 output_rotate_damage(output, output_damage);
902
903 pixman_region32_union(&total_damage, &buffer_damage, output_damage);
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300904
Jason Ekstranda7af7042013-10-12 22:38:11 -0500905 repaint_views(output, &total_damage);
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +0200906
907 pixman_region32_fini(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200908 pixman_region32_fini(&buffer_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400909
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500910 if (gr->border.texture) {
911 draw_global_border(output);
912 } else {
913 draw_output_border(output);
914 }
John Kåre Alsaker44154502012-11-13 19:10:20 +0100915
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +0200916 pixman_region32_copy(&output->previous_damage, output_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400917 wl_signal_emit(&output->frame_signal, output);
918
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100919 ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400920 if (ret == EGL_FALSE && !errored) {
921 errored = 1;
922 weston_log("Failed in eglSwapBuffers.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +0200923 gl_renderer_print_egl_error_state();
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400924 }
925
926}
Kristian Høgsberg25894fc2012-09-05 22:06:26 -0400927
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100928static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100929gl_renderer_read_pixels(struct weston_output *output,
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100930 pixman_format_code_t format, void *pixels,
931 uint32_t x, uint32_t y,
932 uint32_t width, uint32_t height)
933{
934 GLenum gl_format;
935
936 switch (format) {
937 case PIXMAN_a8r8g8b8:
938 gl_format = GL_BGRA_EXT;
939 break;
940 case PIXMAN_a8b8g8r8:
941 gl_format = GL_RGBA;
942 break;
943 default:
944 return -1;
945 }
946
947 if (use_output(output) < 0)
948 return -1;
949
950 glPixelStorei(GL_PACK_ALIGNMENT, 1);
951 glReadPixels(x, y, width, height, gl_format,
952 GL_UNSIGNED_BYTE, pixels);
953
954 return 0;
955}
956
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400957static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100958gl_renderer_flush_damage(struct weston_surface *surface)
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400959{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100960 struct gl_renderer *gr = get_renderer(surface->compositor);
961 struct gl_surface_state *gs = get_surface_state(surface);
Jason Ekstrand6bd62942013-06-20 20:38:23 -0500962 struct weston_buffer *buffer = gs->buffer_ref.buffer;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500963 struct weston_view *view;
964 int texture_used;
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200965 GLenum format;
966 int pixel_type;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100967
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700968#ifdef GL_EXT_unpack_subimage
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400969 pixman_box32_t *rectangles;
970 void *data;
971 int i, n;
972#endif
973
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200974 pixman_region32_union(&gs->texture_damage,
975 &gs->texture_damage, &surface->damage);
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200976
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200977 if (!buffer)
978 return;
979
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200980 /* Avoid upload, if the texture won't be used this time.
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200981 * We still accumulate the damage in texture_damage, and
982 * hold the reference to the buffer, in case the surface
983 * migrates back to the primary plane.
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200984 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500985 texture_used = 0;
986 wl_list_for_each(view, &surface->views, surface_link) {
987 if (view->plane == &surface->compositor->primary_plane) {
988 texture_used = 1;
989 break;
990 }
991 }
992 if (!texture_used)
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200993 return;
994
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200995 if (!pixman_region32_not_empty(&gs->texture_damage))
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200996 goto done;
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200997
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200998 switch (wl_shm_buffer_get_format(buffer->shm_buffer)) {
999 case WL_SHM_FORMAT_XRGB8888:
1000 case WL_SHM_FORMAT_ARGB8888:
1001 format = GL_BGRA_EXT;
1002 pixel_type = GL_UNSIGNED_BYTE;
1003 break;
1004 case WL_SHM_FORMAT_RGB565:
1005 format = GL_RGB;
1006 pixel_type = GL_UNSIGNED_SHORT_5_6_5;
1007 break;
1008 default:
1009 weston_log("warning: unknown shm buffer format\n");
1010 format = GL_BGRA_EXT;
1011 pixel_type = GL_UNSIGNED_BYTE;
1012 }
1013
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001014 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001015
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001016 if (!gr->has_unpack_subimage) {
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001017 glTexImage2D(GL_TEXTURE_2D, 0, format,
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001018 gs->pitch, buffer->height, 0,
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001019 format, pixel_type,
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001020 wl_shm_buffer_get_data(buffer->shm_buffer));
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001021
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001022 goto done;
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001023 }
1024
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -07001025#ifdef GL_EXT_unpack_subimage
1026 glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, gs->pitch);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001027 data = wl_shm_buffer_get_data(buffer->shm_buffer);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +03001028
1029 if (gs->needs_full_upload) {
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -07001030 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
1031 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +03001032 glTexSubImage2D(GL_TEXTURE_2D, 0,
1033 0, 0, gs->pitch, buffer->height,
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001034 format, pixel_type, data);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +03001035 goto done;
1036 }
1037
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001038 rectangles = pixman_region32_rectangles(&gs->texture_damage, &n);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001039 for (i = 0; i < n; i++) {
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +02001040 pixman_box32_t r;
1041
1042 r = weston_surface_to_buffer_rect(surface, rectangles[i]);
1043
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -07001044 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, r.x1);
1045 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, r.y1);
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +02001046 glTexSubImage2D(GL_TEXTURE_2D, 0, r.x1, r.y1,
1047 r.x2 - r.x1, r.y2 - r.y1,
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001048 format, pixel_type, data);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001049 }
1050#endif
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001051
1052done:
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001053 pixman_region32_fini(&gs->texture_damage);
1054 pixman_region32_init(&gs->texture_damage);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +03001055 gs->needs_full_upload = 0;
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001056
1057 weston_buffer_reference(&gs->buffer_ref, NULL);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001058}
1059
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001060static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001061ensure_textures(struct gl_surface_state *gs, int num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001062{
1063 int i;
1064
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001065 if (num_textures <= gs->num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001066 return;
1067
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001068 for (i = gs->num_textures; i < num_textures; i++) {
1069 glGenTextures(1, &gs->textures[i]);
1070 glBindTexture(gs->target, gs->textures[i]);
1071 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001072 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001073 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001074 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1075 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001076 gs->num_textures = num_textures;
1077 glBindTexture(gs->target, 0);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001078}
1079
Kristian Høgsbergfa1be022012-09-05 22:49:55 -04001080static void
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001081gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
1082 struct wl_shm_buffer *shm_buffer)
1083{
1084 struct weston_compositor *ec = es->compositor;
1085 struct gl_renderer *gr = get_renderer(ec);
1086 struct gl_surface_state *gs = get_surface_state(es);
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001087 int pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001088
1089 buffer->shm_buffer = shm_buffer;
1090 buffer->width = wl_shm_buffer_get_width(shm_buffer);
1091 buffer->height = wl_shm_buffer_get_height(shm_buffer);
1092
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001093 switch (wl_shm_buffer_get_format(shm_buffer)) {
1094 case WL_SHM_FORMAT_XRGB8888:
1095 gs->shader = &gr->texture_shader_rgbx;
1096 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
1097 break;
1098 case WL_SHM_FORMAT_ARGB8888:
1099 gs->shader = &gr->texture_shader_rgba;
1100 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
1101 break;
1102 case WL_SHM_FORMAT_RGB565:
1103 gs->shader = &gr->texture_shader_rgbx;
1104 pitch = wl_shm_buffer_get_stride(shm_buffer) / 2;
1105 break;
1106 default:
1107 weston_log("warning: unknown shm buffer format\n");
1108 gs->shader = &gr->texture_shader_rgba;
1109 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
1110 }
1111
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001112 /* Only allocate a texture if it doesn't match existing one.
1113 * If a switch from DRM allocated buffer to a SHM buffer is
1114 * happening, we need to allocate a new texture buffer. */
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001115 if (pitch != gs->pitch ||
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001116 buffer->height != gs->height ||
1117 gs->buffer_type != BUFFER_TYPE_SHM) {
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001118 gs->pitch = pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001119 gs->height = buffer->height;
1120 gs->target = GL_TEXTURE_2D;
1121 gs->buffer_type = BUFFER_TYPE_SHM;
1122 gs->needs_full_upload = 1;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001123 gs->y_inverted = 1;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001124
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001125 gs->surface = es;
1126
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001127 ensure_textures(gs, 1);
1128 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
1129 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1130 gs->pitch, buffer->height, 0,
1131 GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
1132 }
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001133}
1134
1135static void
1136gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
1137 uint32_t format)
1138{
1139 struct weston_compositor *ec = es->compositor;
1140 struct gl_renderer *gr = get_renderer(ec);
1141 struct gl_surface_state *gs = get_surface_state(es);
1142 EGLint attribs[3];
1143 int i, num_planes;
1144
1145 buffer->legacy_buffer = (struct wl_buffer *)buffer->resource;
1146 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1147 EGL_WIDTH, &buffer->width);
1148 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1149 EGL_HEIGHT, &buffer->height);
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001150 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1151 EGL_WAYLAND_Y_INVERTED_WL, &buffer->y_inverted);
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001152
1153 for (i = 0; i < gs->num_images; i++)
1154 gr->destroy_image(gr->egl_display, gs->images[i]);
1155 gs->num_images = 0;
1156 gs->target = GL_TEXTURE_2D;
1157 switch (format) {
1158 case EGL_TEXTURE_RGB:
1159 case EGL_TEXTURE_RGBA:
1160 default:
1161 num_planes = 1;
1162 gs->shader = &gr->texture_shader_rgba;
1163 break;
1164 case EGL_TEXTURE_EXTERNAL_WL:
1165 num_planes = 1;
1166 gs->target = GL_TEXTURE_EXTERNAL_OES;
1167 gs->shader = &gr->texture_shader_egl_external;
1168 break;
1169 case EGL_TEXTURE_Y_UV_WL:
1170 num_planes = 2;
1171 gs->shader = &gr->texture_shader_y_uv;
1172 break;
1173 case EGL_TEXTURE_Y_U_V_WL:
1174 num_planes = 3;
1175 gs->shader = &gr->texture_shader_y_u_v;
1176 break;
1177 case EGL_TEXTURE_Y_XUXV_WL:
1178 num_planes = 2;
1179 gs->shader = &gr->texture_shader_y_xuxv;
1180 break;
1181 }
1182
1183 ensure_textures(gs, num_planes);
1184 for (i = 0; i < num_planes; i++) {
1185 attribs[0] = EGL_WAYLAND_PLANE_WL;
1186 attribs[1] = i;
1187 attribs[2] = EGL_NONE;
1188 gs->images[i] = gr->create_image(gr->egl_display,
1189 NULL,
1190 EGL_WAYLAND_BUFFER_WL,
1191 buffer->legacy_buffer,
1192 attribs);
1193 if (!gs->images[i]) {
1194 weston_log("failed to create img for plane %d\n", i);
1195 continue;
1196 }
1197 gs->num_images++;
1198
1199 glActiveTexture(GL_TEXTURE0 + i);
1200 glBindTexture(gs->target, gs->textures[i]);
1201 gr->image_target_texture_2d(gs->target,
1202 gs->images[i]);
1203 }
1204
1205 gs->pitch = buffer->width;
1206 gs->height = buffer->height;
1207 gs->buffer_type = BUFFER_TYPE_EGL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001208 gs->y_inverted = buffer->y_inverted;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001209}
1210
1211static void
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001212gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001213{
1214 struct weston_compositor *ec = es->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001215 struct gl_renderer *gr = get_renderer(ec);
1216 struct gl_surface_state *gs = get_surface_state(es);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001217 struct wl_shm_buffer *shm_buffer;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001218 EGLint format;
1219 int i;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001220
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001221 weston_buffer_reference(&gs->buffer_ref, buffer);
1222
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001223 if (!buffer) {
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001224 for (i = 0; i < gs->num_images; i++) {
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001225 gr->destroy_image(gr->egl_display, gs->images[i]);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001226 gs->images[i] = NULL;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001227 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001228 gs->num_images = 0;
1229 glDeleteTextures(gs->num_textures, gs->textures);
1230 gs->num_textures = 0;
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001231 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001232 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001233 return;
1234 }
1235
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001236 shm_buffer = wl_shm_buffer_get(buffer->resource);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001237
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001238 if (shm_buffer)
1239 gl_renderer_attach_shm(es, buffer, shm_buffer);
Kristian Høgsberg47229392013-08-07 11:59:54 -07001240 else if (gr->query_buffer(gr->egl_display, (void *) buffer->resource,
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001241 EGL_TEXTURE_FORMAT, &format))
1242 gl_renderer_attach_egl(es, buffer, format);
1243 else {
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001244 weston_log("unhandled buffer type!\n");
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001245 weston_buffer_reference(&gs->buffer_ref, NULL);
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001246 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001247 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001248 }
1249}
1250
Kristian Høgsberg42263852012-09-06 21:59:29 -04001251static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001252gl_renderer_surface_set_color(struct weston_surface *surface,
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001253 float red, float green, float blue, float alpha)
1254{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001255 struct gl_surface_state *gs = get_surface_state(surface);
1256 struct gl_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001257
1258 gs->color[0] = red;
1259 gs->color[1] = green;
1260 gs->color[2] = blue;
1261 gs->color[3] = alpha;
1262
John Kåre Alsaker40684142012-11-13 19:10:25 +01001263 gs->shader = &gr->solid_shader;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001264}
1265
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001266static void
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001267surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr)
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001268{
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001269 int i;
1270
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001271 wl_list_remove(&gs->surface_destroy_listener.link);
1272 wl_list_remove(&gs->renderer_destroy_listener.link);
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001273
1274 gs->surface->renderer_state = NULL;
1275
1276 glDeleteTextures(gs->num_textures, gs->textures);
1277
1278 for (i = 0; i < gs->num_images; i++)
1279 gr->destroy_image(gr->egl_display, gs->images[i]);
1280
1281 weston_buffer_reference(&gs->buffer_ref, NULL);
1282 pixman_region32_fini(&gs->texture_damage);
1283 free(gs);
1284}
1285
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001286static void
1287surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
1288{
1289 struct gl_surface_state *gs;
1290 struct gl_renderer *gr;
1291
1292 gs = container_of(listener, struct gl_surface_state,
1293 surface_destroy_listener);
1294
1295 gr = get_renderer(gs->surface->compositor);
1296
1297 surface_state_destroy(gs, gr);
1298}
1299
1300static void
1301surface_state_handle_renderer_destroy(struct wl_listener *listener, void *data)
1302{
1303 struct gl_surface_state *gs;
1304 struct gl_renderer *gr;
1305
1306 gr = data;
1307
1308 gs = container_of(listener, struct gl_surface_state,
1309 renderer_destroy_listener);
1310
1311 surface_state_destroy(gs, gr);
1312}
1313
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001314static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001315gl_renderer_create_surface(struct weston_surface *surface)
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001316{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001317 struct gl_surface_state *gs;
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001318 struct gl_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001319
1320 gs = calloc(1, sizeof *gs);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001321 if (!gs)
1322 return -1;
1323
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001324 /* A buffer is never attached to solid color surfaces, yet
1325 * they still go through texcoord computations. Do not divide
1326 * by zero there.
1327 */
1328 gs->pitch = 1;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001329 gs->y_inverted = 1;
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001330
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001331 gs->surface = surface;
1332
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001333 pixman_region32_init(&gs->texture_damage);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001334 surface->renderer_state = gs;
1335
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001336 gs->surface_destroy_listener.notify =
1337 surface_state_handle_surface_destroy;
1338 wl_signal_add(&surface->destroy_signal,
1339 &gs->surface_destroy_listener);
1340
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001341 gs->renderer_destroy_listener.notify =
1342 surface_state_handle_renderer_destroy;
1343 wl_signal_add(&gr->destroy_signal,
1344 &gs->renderer_destroy_listener);
1345
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001346 return 0;
1347}
1348
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001349static const char vertex_shader[] =
1350 "uniform mat4 proj;\n"
1351 "attribute vec2 position;\n"
1352 "attribute vec2 texcoord;\n"
1353 "varying vec2 v_texcoord;\n"
1354 "void main()\n"
1355 "{\n"
1356 " gl_Position = proj * vec4(position, 0.0, 1.0);\n"
1357 " v_texcoord = texcoord;\n"
1358 "}\n";
1359
1360/* Declare common fragment shader uniforms */
1361#define FRAGMENT_CONVERT_YUV \
1362 " y *= alpha;\n" \
1363 " u *= alpha;\n" \
1364 " v *= alpha;\n" \
1365 " gl_FragColor.r = y + 1.59602678 * v;\n" \
1366 " gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n" \
1367 " gl_FragColor.b = y + 2.01723214 * u;\n" \
1368 " gl_FragColor.a = alpha;\n"
1369
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001370static const char fragment_debug[] =
1371 " gl_FragColor = vec4(0.0, 0.3, 0.0, 0.2) + gl_FragColor * 0.8;\n";
1372
1373static const char fragment_brace[] =
1374 "}\n";
1375
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001376static const char texture_fragment_shader_rgba[] =
1377 "precision mediump float;\n"
1378 "varying vec2 v_texcoord;\n"
1379 "uniform sampler2D tex;\n"
1380 "uniform float alpha;\n"
1381 "void main()\n"
1382 "{\n"
1383 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001384 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001385
1386static const char texture_fragment_shader_rgbx[] =
1387 "precision mediump float;\n"
1388 "varying vec2 v_texcoord;\n"
1389 "uniform sampler2D tex;\n"
1390 "uniform float alpha;\n"
1391 "void main()\n"
1392 "{\n"
1393 " gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb\n;"
1394 " gl_FragColor.a = alpha;\n"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001395 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001396
1397static const char texture_fragment_shader_egl_external[] =
1398 "#extension GL_OES_EGL_image_external : require\n"
1399 "precision mediump float;\n"
1400 "varying vec2 v_texcoord;\n"
1401 "uniform samplerExternalOES tex;\n"
1402 "uniform float alpha;\n"
1403 "void main()\n"
1404 "{\n"
1405 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001406 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001407
1408static const char texture_fragment_shader_y_uv[] =
1409 "precision mediump float;\n"
1410 "uniform sampler2D tex;\n"
1411 "uniform sampler2D tex1;\n"
1412 "varying vec2 v_texcoord;\n"
1413 "uniform float alpha;\n"
1414 "void main() {\n"
1415 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1416 " float u = texture2D(tex1, v_texcoord).r - 0.5;\n"
1417 " float v = texture2D(tex1, v_texcoord).g - 0.5;\n"
1418 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001419 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001420
1421static const char texture_fragment_shader_y_u_v[] =
1422 "precision mediump float;\n"
1423 "uniform sampler2D tex;\n"
1424 "uniform sampler2D tex1;\n"
1425 "uniform sampler2D tex2;\n"
1426 "varying vec2 v_texcoord;\n"
1427 "uniform float alpha;\n"
1428 "void main() {\n"
1429 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1430 " float u = texture2D(tex1, v_texcoord).x - 0.5;\n"
1431 " float v = texture2D(tex2, v_texcoord).x - 0.5;\n"
1432 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001433 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001434
1435static const char texture_fragment_shader_y_xuxv[] =
1436 "precision mediump float;\n"
1437 "uniform sampler2D tex;\n"
1438 "uniform sampler2D tex1;\n"
1439 "varying vec2 v_texcoord;\n"
1440 "uniform float alpha;\n"
1441 "void main() {\n"
1442 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1443 " float u = texture2D(tex1, v_texcoord).g - 0.5;\n"
1444 " float v = texture2D(tex1, v_texcoord).a - 0.5;\n"
1445 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001446 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001447
1448static const char solid_fragment_shader[] =
1449 "precision mediump float;\n"
1450 "uniform vec4 color;\n"
1451 "uniform float alpha;\n"
1452 "void main()\n"
1453 "{\n"
1454 " gl_FragColor = alpha * color\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001455 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001456
1457static int
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001458compile_shader(GLenum type, int count, const char **sources)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001459{
1460 GLuint s;
1461 char msg[512];
1462 GLint status;
1463
1464 s = glCreateShader(type);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001465 glShaderSource(s, count, sources, NULL);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001466 glCompileShader(s);
1467 glGetShaderiv(s, GL_COMPILE_STATUS, &status);
1468 if (!status) {
1469 glGetShaderInfoLog(s, sizeof msg, NULL, msg);
1470 weston_log("shader info: %s\n", msg);
1471 return GL_NONE;
1472 }
1473
1474 return s;
1475}
1476
1477static int
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03001478shader_init(struct gl_shader *shader, struct gl_renderer *renderer,
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001479 const char *vertex_source, const char *fragment_source)
1480{
1481 char msg[512];
1482 GLint status;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001483 int count;
1484 const char *sources[3];
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001485
1486 shader->vertex_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001487 compile_shader(GL_VERTEX_SHADER, 1, &vertex_source);
1488
1489 if (renderer->fragment_shader_debug) {
1490 sources[0] = fragment_source;
1491 sources[1] = fragment_debug;
1492 sources[2] = fragment_brace;
1493 count = 3;
1494 } else {
1495 sources[0] = fragment_source;
1496 sources[1] = fragment_brace;
1497 count = 2;
1498 }
1499
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001500 shader->fragment_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001501 compile_shader(GL_FRAGMENT_SHADER, count, sources);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001502
1503 shader->program = glCreateProgram();
1504 glAttachShader(shader->program, shader->vertex_shader);
1505 glAttachShader(shader->program, shader->fragment_shader);
1506 glBindAttribLocation(shader->program, 0, "position");
1507 glBindAttribLocation(shader->program, 1, "texcoord");
1508
1509 glLinkProgram(shader->program);
1510 glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
1511 if (!status) {
1512 glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
1513 weston_log("link info: %s\n", msg);
1514 return -1;
1515 }
1516
1517 shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
1518 shader->tex_uniforms[0] = glGetUniformLocation(shader->program, "tex");
1519 shader->tex_uniforms[1] = glGetUniformLocation(shader->program, "tex1");
1520 shader->tex_uniforms[2] = glGetUniformLocation(shader->program, "tex2");
1521 shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
1522 shader->color_uniform = glGetUniformLocation(shader->program, "color");
1523
1524 return 0;
1525}
1526
1527static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001528shader_release(struct gl_shader *shader)
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001529{
1530 glDeleteShader(shader->vertex_shader);
1531 glDeleteShader(shader->fragment_shader);
1532 glDeleteProgram(shader->program);
1533
1534 shader->vertex_shader = 0;
1535 shader->fragment_shader = 0;
1536 shader->program = 0;
1537}
1538
1539static void
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001540log_extensions(const char *name, const char *extensions)
1541{
1542 const char *p, *end;
1543 int l;
1544 int len;
1545
1546 l = weston_log("%s:", name);
1547 p = extensions;
1548 while (*p) {
1549 end = strchrnul(p, ' ');
1550 len = end - p;
1551 if (l + len > 78)
1552 l = weston_log_continue("\n" STAMP_SPACE "%.*s",
1553 len, p);
1554 else
1555 l += weston_log_continue(" %.*s", len, p);
1556 for (p = end; isspace(*p); p++)
1557 ;
1558 }
1559 weston_log_continue("\n");
1560}
1561
1562static void
1563log_egl_gl_info(EGLDisplay egldpy)
1564{
1565 const char *str;
1566
1567 str = eglQueryString(egldpy, EGL_VERSION);
1568 weston_log("EGL version: %s\n", str ? str : "(null)");
1569
1570 str = eglQueryString(egldpy, EGL_VENDOR);
1571 weston_log("EGL vendor: %s\n", str ? str : "(null)");
1572
1573 str = eglQueryString(egldpy, EGL_CLIENT_APIS);
1574 weston_log("EGL client APIs: %s\n", str ? str : "(null)");
1575
1576 str = eglQueryString(egldpy, EGL_EXTENSIONS);
1577 log_extensions("EGL extensions", str ? str : "(null)");
1578
1579 str = (char *)glGetString(GL_VERSION);
1580 weston_log("GL version: %s\n", str ? str : "(null)");
1581
1582 str = (char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
1583 weston_log("GLSL version: %s\n", str ? str : "(null)");
1584
1585 str = (char *)glGetString(GL_VENDOR);
1586 weston_log("GL vendor: %s\n", str ? str : "(null)");
1587
1588 str = (char *)glGetString(GL_RENDERER);
1589 weston_log("GL renderer: %s\n", str ? str : "(null)");
1590
1591 str = (char *)glGetString(GL_EXTENSIONS);
1592 log_extensions("GL extensions", str ? str : "(null)");
1593}
1594
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001595static void
1596log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
1597{
1598 EGLint r, g, b, a;
1599
1600 weston_log("Chosen EGL config details:\n");
1601
1602 weston_log_continue(STAMP_SPACE "RGBA bits");
1603 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_RED_SIZE, &r) &&
1604 eglGetConfigAttrib(egldpy, eglconfig, EGL_GREEN_SIZE, &g) &&
1605 eglGetConfigAttrib(egldpy, eglconfig, EGL_BLUE_SIZE, &b) &&
1606 eglGetConfigAttrib(egldpy, eglconfig, EGL_ALPHA_SIZE, &a))
1607 weston_log_continue(": %d %d %d %d\n", r, g, b, a);
1608 else
1609 weston_log_continue(" unknown\n");
1610
1611 weston_log_continue(STAMP_SPACE "swap interval range");
1612 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_MIN_SWAP_INTERVAL, &a) &&
1613 eglGetConfigAttrib(egldpy, eglconfig, EGL_MAX_SWAP_INTERVAL, &b))
1614 weston_log_continue(": %d - %d\n", a, b);
1615 else
1616 weston_log_continue(" unknown\n");
1617}
1618
John Kåre Alsaker44154502012-11-13 19:10:20 +01001619static void
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05001620gl_renderer_output_set_border(struct weston_output *output,
1621 enum gl_renderer_border_side side,
1622 int32_t width, int32_t height,
1623 int32_t tex_width, unsigned char *data)
1624{
1625 struct gl_output_state *go = get_output_state(output);
1626
1627 go->borders[side].width = width;
1628 go->borders[side].height = height;
1629 go->borders[side].tex_width = tex_width;
1630 go->borders[side].data = data;
1631 go->borders[side].dirty = 1;
1632}
1633
1634static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001635output_apply_border(struct weston_output *output, struct gl_renderer *gr)
John Kåre Alsaker44154502012-11-13 19:10:20 +01001636{
1637 output->border.top = gr->border.top;
1638 output->border.bottom = gr->border.bottom;
1639 output->border.left = gr->border.left;
1640 output->border.right = gr->border.right;
1641}
1642
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001643static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001644gl_renderer_set_border(struct weston_compositor *ec, int32_t width, int32_t height, void *data,
John Kåre Alsaker44154502012-11-13 19:10:20 +01001645 int32_t *edges)
1646{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001647 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker44154502012-11-13 19:10:20 +01001648 struct weston_output *output;
1649
1650 gr->border.left = edges[0];
1651 gr->border.right = edges[1];
1652 gr->border.top = edges[2];
1653 gr->border.bottom = edges[3];
1654
1655 gr->border.width = width;
1656 gr->border.height = height;
1657
1658 glGenTextures(1, &gr->border.texture);
1659 glBindTexture(GL_TEXTURE_2D, gr->border.texture);
1660 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1661 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1662 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1663 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1664
1665 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1666 width,
1667 height,
1668 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
1669 data);
1670
1671 wl_list_for_each(output, &ec->output_list, link)
1672 output_apply_border(output, gr);
1673}
1674
John Kåre Alsaker94659272012-11-13 19:10:18 +01001675static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001676gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001677
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001678static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001679gl_renderer_output_create(struct weston_output *output,
John Kåre Alsaker94659272012-11-13 19:10:18 +01001680 EGLNativeWindowType window)
1681{
1682 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001683 struct gl_renderer *gr = get_renderer(ec);
1684 struct gl_output_state *go = calloc(1, sizeof *go);
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001685 int i;
John Kåre Alsaker94659272012-11-13 19:10:18 +01001686
1687 if (!go)
1688 return -1;
1689
1690 go->egl_surface =
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001691 eglCreateWindowSurface(gr->egl_display,
1692 gr->egl_config,
John Kåre Alsaker94659272012-11-13 19:10:18 +01001693 window, NULL);
1694
1695 if (go->egl_surface == EGL_NO_SURFACE) {
1696 weston_log("failed to create egl surface\n");
1697 free(go);
1698 return -1;
1699 }
1700
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001701 if (gr->egl_context == NULL)
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001702 if (gl_renderer_setup(ec, go->egl_surface) < 0) {
John Kåre Alsaker94659272012-11-13 19:10:18 +01001703 free(go);
1704 return -1;
1705 }
1706
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001707 for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001708 pixman_region32_init(&go->buffer_damage[i]);
1709
John Kåre Alsaker94659272012-11-13 19:10:18 +01001710 output->renderer_state = go;
1711
John Kåre Alsaker44154502012-11-13 19:10:20 +01001712 output_apply_border(output, gr);
1713
John Kåre Alsaker94659272012-11-13 19:10:18 +01001714 return 0;
1715}
1716
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001717static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001718gl_renderer_output_destroy(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01001719{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001720 struct gl_renderer *gr = get_renderer(output->compositor);
1721 struct gl_output_state *go = get_output_state(output);
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001722 int i;
1723
1724 for (i = 0; i < 2; i++)
1725 pixman_region32_fini(&go->buffer_damage[i]);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001726
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001727 eglDestroySurface(gr->egl_display, go->egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001728
1729 free(go);
1730}
1731
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001732static EGLSurface
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001733gl_renderer_output_surface(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01001734{
1735 return get_output_state(output)->egl_surface;
1736}
1737
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03001738static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001739gl_renderer_destroy(struct weston_compositor *ec)
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001740{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001741 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001742
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001743 wl_signal_emit(&gr->destroy_signal, gr);
1744
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001745 if (gr->has_bind_display)
1746 gr->unbind_display(gr->egl_display, ec->wl_display);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001747
1748 /* Work around crash in egl_dri2.c's dri2_make_current() - when does this apply? */
1749 eglMakeCurrent(gr->egl_display,
1750 EGL_NO_SURFACE, EGL_NO_SURFACE,
1751 EGL_NO_CONTEXT);
1752
1753 eglTerminate(gr->egl_display);
1754 eglReleaseThread();
Scott Moreau976a0502013-03-07 10:15:17 -07001755
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -04001756 wl_array_release(&gr->vertices);
1757 wl_array_release(&gr->indices);
1758 wl_array_release(&gr->vtxcnt);
1759
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +03001760 weston_binding_destroy(gr->fragment_binding);
1761 weston_binding_destroy(gr->fan_binding);
1762
Scott Moreau976a0502013-03-07 10:15:17 -07001763 free(gr);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001764}
1765
1766static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001767egl_choose_config(struct gl_renderer *gr, const EGLint *attribs,
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001768 const EGLint *visual_id)
1769{
1770 EGLint count = 0;
1771 EGLint matched = 0;
1772 EGLConfig *configs;
1773 int i;
1774
1775 if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1)
1776 return -1;
1777
1778 configs = calloc(count, sizeof *configs);
1779 if (!configs)
1780 return -1;
1781
1782 if (!eglChooseConfig(gr->egl_display, attribs, configs,
1783 count, &matched))
1784 goto out;
1785
1786 for (i = 0; i < matched; ++i) {
1787 EGLint id;
1788
1789 if (visual_id) {
1790 if (!eglGetConfigAttrib(gr->egl_display,
1791 configs[i], EGL_NATIVE_VISUAL_ID,
1792 &id))
1793 continue;
1794
Kristian Høgsbergc3ea26c2013-09-25 15:46:42 -07001795 if (id != 0 && id != *visual_id)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001796 continue;
1797 }
1798
1799 gr->egl_config = configs[i];
1800
1801 free(configs);
1802 return 0;
1803 }
1804
1805out:
1806 free(configs);
1807 return -1;
1808}
1809
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001810static const EGLint gl_renderer_opaque_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001811 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1812 EGL_RED_SIZE, 1,
1813 EGL_GREEN_SIZE, 1,
1814 EGL_BLUE_SIZE, 1,
1815 EGL_ALPHA_SIZE, 0,
1816 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1817 EGL_NONE
1818};
1819
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001820static const EGLint gl_renderer_alpha_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001821 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1822 EGL_RED_SIZE, 1,
1823 EGL_GREEN_SIZE, 1,
1824 EGL_BLUE_SIZE, 1,
1825 EGL_ALPHA_SIZE, 1,
1826 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1827 EGL_NONE
1828};
1829
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001830static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001831gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001832 const EGLint *attribs, const EGLint *visual_id)
1833{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001834 struct gl_renderer *gr;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001835 EGLint major, minor;
1836
1837 gr = calloc(1, sizeof *gr);
1838
1839 if (gr == NULL)
1840 return -1;
1841
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001842 gr->base.read_pixels = gl_renderer_read_pixels;
1843 gr->base.repaint_output = gl_renderer_repaint_output;
1844 gr->base.flush_damage = gl_renderer_flush_damage;
1845 gr->base.attach = gl_renderer_attach;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001846 gr->base.surface_set_color = gl_renderer_surface_set_color;
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03001847 gr->base.destroy = gl_renderer_destroy;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001848
1849 gr->egl_display = eglGetDisplay(display);
1850 if (gr->egl_display == EGL_NO_DISPLAY) {
1851 weston_log("failed to create display\n");
1852 goto err_egl;
1853 }
1854
1855 if (!eglInitialize(gr->egl_display, &major, &minor)) {
1856 weston_log("failed to initialize display\n");
1857 goto err_egl;
1858 }
1859
1860 if (egl_choose_config(gr, attribs, visual_id) < 0) {
1861 weston_log("failed to choose EGL config\n");
1862 goto err_egl;
1863 }
1864
1865 ec->renderer = &gr->base;
Pekka Paalanen7bb65102013-05-22 18:03:04 +03001866 ec->capabilities |= WESTON_CAP_ROTATION_ANY;
Pekka Paalanen4fc5dd02013-05-22 18:03:05 +03001867 ec->capabilities |= WESTON_CAP_CAPTURE_YFLIP;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001868
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001869 wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565);
1870
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001871 wl_signal_init(&gr->destroy_signal);
1872
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001873 return 0;
1874
1875err_egl:
Pekka Paalanen326529f2012-11-27 12:25:25 +02001876 gl_renderer_print_egl_error_state();
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001877 free(gr);
1878 return -1;
1879}
1880
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001881static EGLDisplay
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001882gl_renderer_display(struct weston_compositor *ec)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001883{
1884 return get_renderer(ec)->egl_display;
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001885}
1886
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001887static int
1888compile_shaders(struct weston_compositor *ec)
1889{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001890 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker40684142012-11-13 19:10:25 +01001891
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03001892 gr->texture_shader_rgba.vertex_source = vertex_shader;
1893 gr->texture_shader_rgba.fragment_source = texture_fragment_shader_rgba;
1894
1895 gr->texture_shader_rgbx.vertex_source = vertex_shader;
1896 gr->texture_shader_rgbx.fragment_source = texture_fragment_shader_rgbx;
1897
1898 gr->texture_shader_egl_external.vertex_source = vertex_shader;
1899 gr->texture_shader_egl_external.fragment_source =
1900 texture_fragment_shader_egl_external;
1901
1902 gr->texture_shader_y_uv.vertex_source = vertex_shader;
1903 gr->texture_shader_y_uv.fragment_source = texture_fragment_shader_y_uv;
1904
1905 gr->texture_shader_y_u_v.vertex_source = vertex_shader;
1906 gr->texture_shader_y_u_v.fragment_source =
1907 texture_fragment_shader_y_u_v;
1908
1909 gr->texture_shader_y_u_v.vertex_source = vertex_shader;
1910 gr->texture_shader_y_xuxv.fragment_source =
1911 texture_fragment_shader_y_xuxv;
1912
1913 gr->solid_shader.vertex_source = vertex_shader;
1914 gr->solid_shader.fragment_source = solid_fragment_shader;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001915
1916 return 0;
1917}
1918
1919static void
Kristian Høgsberge3148752013-05-06 23:19:49 -04001920fragment_debug_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001921 void *data)
1922{
1923 struct weston_compositor *ec = data;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001924 struct gl_renderer *gr = get_renderer(ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001925 struct weston_output *output;
1926
John Kåre Alsaker40684142012-11-13 19:10:25 +01001927 gr->fragment_shader_debug ^= 1;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001928
John Kåre Alsaker40684142012-11-13 19:10:25 +01001929 shader_release(&gr->texture_shader_rgba);
1930 shader_release(&gr->texture_shader_rgbx);
1931 shader_release(&gr->texture_shader_egl_external);
1932 shader_release(&gr->texture_shader_y_uv);
1933 shader_release(&gr->texture_shader_y_u_v);
1934 shader_release(&gr->texture_shader_y_xuxv);
1935 shader_release(&gr->solid_shader);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001936
Ander Conselvan de Oliveira03fb4ef2012-12-03 17:08:11 +02001937 /* Force use_shader() to call glUseProgram(), since we need to use
1938 * the recompiled version of the shader. */
1939 gr->current_shader = NULL;
1940
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001941 wl_list_for_each(output, &ec->output_list, link)
1942 weston_output_damage(output);
1943}
1944
Kristian Høgsberg8799d412013-05-07 10:50:09 -04001945static void
1946fan_debug_repaint_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
1947 void *data)
1948{
1949 struct weston_compositor *compositor = data;
1950 struct gl_renderer *gr = get_renderer(compositor);
1951
1952 gr->fan_debug = !gr->fan_debug;
1953 weston_compositor_damage_all(compositor);
1954}
1955
John Kåre Alsaker94659272012-11-13 19:10:18 +01001956static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001957gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001958{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001959 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001960 const char *extensions;
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001961 EGLBoolean ret;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001962
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001963 static const EGLint context_attribs[] = {
1964 EGL_CONTEXT_CLIENT_VERSION, 2,
1965 EGL_NONE
1966 };
1967
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001968 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
1969 weston_log("failed to bind EGL_OPENGL_ES_API\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001970 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001971 return -1;
1972 }
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001973
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001974 log_egl_config_info(gr->egl_display, gr->egl_config);
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001975
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001976 gr->egl_context = eglCreateContext(gr->egl_display, gr->egl_config,
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001977 EGL_NO_CONTEXT, context_attribs);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001978 if (gr->egl_context == NULL) {
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001979 weston_log("failed to create context\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001980 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001981 return -1;
1982 }
1983
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001984 ret = eglMakeCurrent(gr->egl_display, egl_surface,
1985 egl_surface, gr->egl_context);
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001986 if (ret == EGL_FALSE) {
1987 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001988 gl_renderer_print_egl_error_state();
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001989 return -1;
1990 }
1991
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001992 log_egl_gl_info(gr->egl_display);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001993
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001994 gr->image_target_texture_2d =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001995 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001996 gr->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
1997 gr->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
1998 gr->bind_display =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001999 (void *) eglGetProcAddress("eglBindWaylandDisplayWL");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002000 gr->unbind_display =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002001 (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002002 gr->query_buffer =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002003 (void *) eglGetProcAddress("eglQueryWaylandBufferWL");
2004
2005 extensions = (const char *) glGetString(GL_EXTENSIONS);
2006 if (!extensions) {
2007 weston_log("Retrieving GL extension string failed.\n");
2008 return -1;
2009 }
2010
2011 if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
2012 weston_log("GL_EXT_texture_format_BGRA8888 not available\n");
2013 return -1;
2014 }
2015
2016 if (strstr(extensions, "GL_EXT_read_format_bgra"))
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01002017 ec->read_format = PIXMAN_a8r8g8b8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002018 else
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01002019 ec->read_format = PIXMAN_a8b8g8r8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002020
Kristian Høgsberg1c4f1632013-08-07 12:11:27 -07002021#ifdef GL_EXT_unpack_subimage
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002022 if (strstr(extensions, "GL_EXT_unpack_subimage"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002023 gr->has_unpack_subimage = 1;
Kristian Høgsberg1c4f1632013-08-07 12:11:27 -07002024#endif
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002025
2026 if (strstr(extensions, "GL_OES_EGL_image_external"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002027 gr->has_egl_image_external = 1;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002028
2029 extensions =
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002030 (const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002031 if (!extensions) {
2032 weston_log("Retrieving EGL extension string failed.\n");
2033 return -1;
2034 }
2035
2036 if (strstr(extensions, "EGL_WL_bind_wayland_display"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002037 gr->has_bind_display = 1;
2038 if (gr->has_bind_display) {
2039 ret = gr->bind_display(gr->egl_display, ec->wl_display);
Pekka Paalanen035a0322012-10-24 09:43:06 +03002040 if (!ret)
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002041 gr->has_bind_display = 0;
Pekka Paalanen035a0322012-10-24 09:43:06 +03002042 }
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002043
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02002044 if (strstr(extensions, "EGL_EXT_buffer_age"))
2045 gr->has_egl_buffer_age = 1;
2046 else
2047 weston_log("warning: EGL_EXT_buffer_age not supported. "
2048 "Performance could be affected.\n");
2049
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002050 glActiveTexture(GL_TEXTURE0);
2051
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002052 if (compile_shaders(ec))
2053 return -1;
2054
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +03002055 gr->fragment_binding =
2056 weston_compositor_add_debug_binding(ec, KEY_S,
2057 fragment_debug_binding,
2058 ec);
2059 gr->fan_binding =
2060 weston_compositor_add_debug_binding(ec, KEY_F,
2061 fan_debug_repaint_binding,
2062 ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002063
Pekka Paalanen035a0322012-10-24 09:43:06 +03002064 weston_log("GL ES 2 renderer features:\n");
2065 weston_log_continue(STAMP_SPACE "read-back format: %s\n",
Pekka Paalanenfe4eacf2013-01-10 16:50:42 +02002066 ec->read_format == PIXMAN_a8r8g8b8 ? "BGRA" : "RGBA");
Pekka Paalanen035a0322012-10-24 09:43:06 +03002067 weston_log_continue(STAMP_SPACE "wl_shm sub-image to texture: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002068 gr->has_unpack_subimage ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03002069 weston_log_continue(STAMP_SPACE "EGL Wayland extension: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002070 gr->has_bind_display ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03002071
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002072
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002073 return 0;
2074}
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002075
2076WL_EXPORT struct gl_renderer_interface gl_renderer_interface = {
2077 .opaque_attribs = gl_renderer_opaque_attribs,
2078 .alpha_attribs = gl_renderer_alpha_attribs,
2079
2080 .create = gl_renderer_create,
2081 .display = gl_renderer_display,
2082 .output_create = gl_renderer_output_create,
2083 .output_destroy = gl_renderer_output_destroy,
2084 .output_surface = gl_renderer_output_surface,
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05002085 .output_set_border = gl_renderer_output_set_border,
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002086 .set_border = gl_renderer_set_border,
2087 .print_egl_error_state = gl_renderer_print_egl_error_state
2088};