blob: 4c7137dc4d2f2c559e7dbae335ca53a5e84b55aa [file] [log] [blame]
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001/*
2 * Copyright © 2012 Intel Corporation
Pekka Paalaneneb35cbe2015-02-09 13:37:27 +02003 * Copyright © 2015 Collabora, Ltd.
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04004 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -07005 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
Kristian Høgsbergd7c17262012-09-05 21:54:15 -040012 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -070013 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
Kristian Høgsbergd7c17262012-09-05 21:54:15 -040025 */
26
Daniel Stonec228e232013-05-22 18:03:19 +030027#include "config.h"
Kristian Høgsberg25894fc2012-09-05 22:06:26 -040028
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010029#include <GLES2/gl2.h>
30#include <GLES2/gl2ext.h>
31
Derek Foremanf8180982014-10-16 16:37:02 -050032#include <stdbool.h>
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -040033#include <stdlib.h>
Kristian Høgsberg25894fc2012-09-05 22:06:26 -040034#include <string.h>
35#include <ctype.h>
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +030036#include <float.h>
37#include <assert.h>
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +020038#include <linux/input.h>
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -040039
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010040#include "gl-renderer.h"
Sam Spilsbury619859c2013-09-13 10:01:21 +080041#include "vertex-clipping.h"
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010042
Jon Cruz35b2eaa2015-06-15 15:37:08 -070043#include "shared/helpers.h"
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010044#include "weston-egl-ext.h"
Kristian Høgsbergd7c17262012-09-05 21:54:15 -040045
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010046struct gl_shader {
John Kåre Alsaker40684142012-11-13 19:10:25 +010047 GLuint program;
48 GLuint vertex_shader, fragment_shader;
49 GLint proj_uniform;
50 GLint tex_uniforms[3];
51 GLint alpha_uniform;
52 GLint color_uniform;
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +030053 const char *vertex_source, *fragment_source;
John Kåre Alsaker40684142012-11-13 19:10:25 +010054};
55
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +020056#define BUFFER_DAMAGE_COUNT 2
57
Jason Ekstrande5512d42014-02-04 21:36:38 -060058enum gl_border_status {
59 BORDER_STATUS_CLEAN = 0,
60 BORDER_TOP_DIRTY = 1 << GL_RENDERER_BORDER_TOP,
61 BORDER_LEFT_DIRTY = 1 << GL_RENDERER_BORDER_LEFT,
62 BORDER_RIGHT_DIRTY = 1 << GL_RENDERER_BORDER_RIGHT,
63 BORDER_BOTTOM_DIRTY = 1 << GL_RENDERER_BORDER_BOTTOM,
64 BORDER_ALL_DIRTY = 0xf,
65 BORDER_SIZE_CHANGED = 0x10
66};
67
Jason Ekstrand0b61bf42013-10-27 22:24:54 -050068struct gl_border_image {
69 GLuint tex;
70 int32_t width, height;
71 int32_t tex_width;
Jason Ekstrand0b61bf42013-10-27 22:24:54 -050072 void *data;
73};
74
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010075struct gl_output_state {
John Kåre Alsaker94659272012-11-13 19:10:18 +010076 EGLSurface egl_surface;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +020077 pixman_region32_t buffer_damage[BUFFER_DAMAGE_COUNT];
Derek Foreman4c582662014-10-09 18:39:44 -050078 int buffer_damage_index;
Jason Ekstrande5512d42014-02-04 21:36:38 -060079 enum gl_border_status border_damage[BUFFER_DAMAGE_COUNT];
Jason Ekstrand0b61bf42013-10-27 22:24:54 -050080 struct gl_border_image borders[4];
Jason Ekstrande5512d42014-02-04 21:36:38 -060081 enum gl_border_status border_status;
Jason Ekstrandfb23df72014-10-16 10:55:21 -050082
83 struct weston_matrix output_matrix;
John Kåre Alsaker94659272012-11-13 19:10:18 +010084};
85
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +030086enum buffer_type {
87 BUFFER_TYPE_NULL,
Pekka Paalanenaeb917e2015-02-09 13:56:56 +020088 BUFFER_TYPE_SOLID, /* internal solid color surfaces without a buffer */
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +030089 BUFFER_TYPE_SHM,
90 BUFFER_TYPE_EGL
91};
92
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +030093struct gl_renderer;
94
95struct egl_image {
96 struct gl_renderer *renderer;
97 EGLImageKHR image;
98 int refcount;
99};
100
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100101struct gl_surface_state {
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100102 GLfloat color[4];
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100103 struct gl_shader *shader;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100104
105 GLuint textures[3];
106 int num_textures;
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300107 int needs_full_upload;
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200108 pixman_region32_t texture_damage;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100109
Neil Roberts4d085e72014-04-07 15:01:01 +0100110 /* These are only used by SHM surfaces to detect when we need
111 * to do a full upload to specify a new internal texture
112 * format */
113 GLenum gl_format;
114 GLenum gl_pixel_type;
115
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +0300116 struct egl_image* images[3];
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100117 GLenum target;
118 int num_images;
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200119
120 struct weston_buffer_reference buffer_ref;
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +0300121 enum buffer_type buffer_type;
Pekka Paalanen68033ac2012-12-04 15:58:15 +0200122 int pitch; /* in pixels */
Alexander Larsson4ea95522013-05-22 14:41:37 +0200123 int height; /* in pixels */
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +0400124 int y_inverted;
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300125
126 struct weston_surface *surface;
127
128 struct wl_listener surface_destroy_listener;
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +0300129 struct wl_listener renderer_destroy_listener;
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100130};
131
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100132struct gl_renderer {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100133 struct weston_renderer base;
134 int fragment_shader_debug;
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400135 int fan_debug;
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +0300136 struct weston_binding *fragment_binding;
137 struct weston_binding *fan_binding;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100138
139 EGLDisplay egl_display;
140 EGLContext egl_context;
141 EGLConfig egl_config;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100142
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400143 struct wl_array vertices;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400144 struct wl_array vtxcnt;
145
John Kåre Alsaker320711d2012-11-13 19:10:27 +0100146 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
147 PFNEGLCREATEIMAGEKHRPROC create_image;
148 PFNEGLDESTROYIMAGEKHRPROC destroy_image;
149
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -0600150#ifdef EGL_EXT_swap_buffers_with_damage
151 PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage;
152#endif
153
Jonny Lamb671148f2015-03-20 15:26:52 +0100154 PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC create_platform_window;
Jonny Lamb671148f2015-03-20 15:26:52 +0100155
John Kåre Alsaker320711d2012-11-13 19:10:27 +0100156 int has_unpack_subimage;
157
158 PFNEGLBINDWAYLANDDISPLAYWL bind_display;
159 PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
160 PFNEGLQUERYWAYLANDBUFFERWL query_buffer;
161 int has_bind_display;
162
163 int has_egl_image_external;
164
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200165 int has_egl_buffer_age;
166
Neil Roberts77c1a5b2014-03-07 18:05:50 +0000167 int has_configless_context;
168
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100169 struct gl_shader texture_shader_rgba;
170 struct gl_shader texture_shader_rgbx;
171 struct gl_shader texture_shader_egl_external;
172 struct gl_shader texture_shader_y_uv;
173 struct gl_shader texture_shader_y_u_v;
174 struct gl_shader texture_shader_y_xuxv;
175 struct gl_shader invert_color_shader;
176 struct gl_shader solid_shader;
177 struct gl_shader *current_shader;
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +0300178
179 struct wl_signal destroy_signal;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100180};
John Kåre Alsaker94659272012-11-13 19:10:18 +0100181
Jonny Lamb70eba3f2015-03-20 15:26:50 +0100182static PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display = NULL;
Jonny Lamb70eba3f2015-03-20 15:26:50 +0100183
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100184static inline struct gl_output_state *
John Kåre Alsaker94659272012-11-13 19:10:18 +0100185get_output_state(struct weston_output *output)
186{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100187 return (struct gl_output_state *)output->renderer_state;
John Kåre Alsaker94659272012-11-13 19:10:18 +0100188}
189
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300190static int
191gl_renderer_create_surface(struct weston_surface *surface);
192
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100193static inline struct gl_surface_state *
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100194get_surface_state(struct weston_surface *surface)
195{
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300196 if (!surface->renderer_state)
197 gl_renderer_create_surface(surface);
198
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100199 return (struct gl_surface_state *)surface->renderer_state;
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100200}
201
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100202static inline struct gl_renderer *
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100203get_renderer(struct weston_compositor *ec)
204{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100205 return (struct gl_renderer *)ec->renderer;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100206}
207
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +0300208static struct egl_image*
209egl_image_create(struct gl_renderer *gr, EGLenum target,
210 EGLClientBuffer buffer, const EGLint *attribs)
211{
212 struct egl_image *img;
213
214 img = zalloc(sizeof *img);
215 img->renderer = gr;
216 img->refcount = 1;
217 img->image = gr->create_image(gr->egl_display, EGL_NO_CONTEXT,
218 target, buffer, attribs);
219
220 if (img->image == EGL_NO_IMAGE_KHR) {
221 free(img);
222 return NULL;
223 }
224
225 return img;
226}
227
228static struct egl_image*
229egl_image_ref(struct egl_image *image)
230{
231 image->refcount++;
232
233 return image;
234}
235
236static int
237egl_image_unref(struct egl_image *image)
238{
239 struct gl_renderer *gr = image->renderer;
240
241 assert(image->refcount > 0);
242
243 image->refcount--;
244 if (image->refcount > 0)
245 return image->refcount;
246
247 gr->destroy_image(gr->egl_display, image->image);
248 free(image);
249
250 return 0;
251}
252
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400253static const char *
254egl_error_string(EGLint code)
255{
256#define MYERRCODE(x) case x: return #x;
257 switch (code) {
258 MYERRCODE(EGL_SUCCESS)
259 MYERRCODE(EGL_NOT_INITIALIZED)
260 MYERRCODE(EGL_BAD_ACCESS)
261 MYERRCODE(EGL_BAD_ALLOC)
262 MYERRCODE(EGL_BAD_ATTRIBUTE)
263 MYERRCODE(EGL_BAD_CONTEXT)
264 MYERRCODE(EGL_BAD_CONFIG)
265 MYERRCODE(EGL_BAD_CURRENT_SURFACE)
266 MYERRCODE(EGL_BAD_DISPLAY)
267 MYERRCODE(EGL_BAD_SURFACE)
268 MYERRCODE(EGL_BAD_MATCH)
269 MYERRCODE(EGL_BAD_PARAMETER)
270 MYERRCODE(EGL_BAD_NATIVE_PIXMAP)
271 MYERRCODE(EGL_BAD_NATIVE_WINDOW)
272 MYERRCODE(EGL_CONTEXT_LOST)
273 default:
274 return "unknown";
275 }
276#undef MYERRCODE
277}
278
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +0300279static void
Pekka Paalanen326529f2012-11-27 12:25:25 +0200280gl_renderer_print_egl_error_state(void)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400281{
282 EGLint code;
283
284 code = eglGetError();
285 weston_log("EGL error state: %s (0x%04lx)\n",
286 egl_error_string(code), (long)code);
287}
288
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400289#define max(a, b) (((a) > (b)) ? (a) : (b))
290#define min(a, b) (((a) > (b)) ? (b) : (a))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400291
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300292/*
293 * Compute the boundary vertices of the intersection of the global coordinate
294 * aligned rectangle 'rect', and an arbitrary quadrilateral produced from
295 * 'surf_rect' when transformed from surface coordinates into global coordinates.
296 * The vertices are written to 'ex' and 'ey', and the return value is the
297 * number of vertices. Vertices are produced in clockwise winding order.
298 * Guarantees to produce either zero vertices, or 3-8 vertices with non-zero
299 * polygon area.
300 */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400301static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500302calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400303 pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
304{
Sam Spilsbury619859c2013-09-13 10:01:21 +0800305
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300306 struct clip_context ctx;
307 int i, n;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400308 GLfloat min_x, max_x, min_y, max_y;
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300309 struct polygon8 surf = {
310 { surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1 },
311 { surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2 },
312 4
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400313 };
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400314
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300315 ctx.clip.x1 = rect->x1;
316 ctx.clip.y1 = rect->y1;
317 ctx.clip.x2 = rect->x2;
318 ctx.clip.y2 = rect->y2;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400319
320 /* transform surface to screen space: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300321 for (i = 0; i < surf.n; i++)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500322 weston_view_to_global_float(ev, surf.x[i], surf.y[i],
323 &surf.x[i], &surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400324
325 /* find bounding box: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300326 min_x = max_x = surf.x[0];
327 min_y = max_y = surf.y[0];
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400328
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300329 for (i = 1; i < surf.n; i++) {
330 min_x = min(min_x, surf.x[i]);
331 max_x = max(max_x, surf.x[i]);
332 min_y = min(min_y, surf.y[i]);
333 max_y = max(max_y, surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400334 }
335
336 /* First, simple bounding box check to discard early transformed
337 * surface rects that do not intersect with the clip region:
338 */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300339 if ((min_x >= ctx.clip.x2) || (max_x <= ctx.clip.x1) ||
340 (min_y >= ctx.clip.y2) || (max_y <= ctx.clip.y1))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400341 return 0;
342
343 /* Simple case, bounding box edges are parallel to surface edges,
344 * there will be only four edges. We just need to clip the surface
345 * vertices to the clip rect bounds:
346 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500347 if (!ev->transform.enabled)
Sam Spilsbury619859c2013-09-13 10:01:21 +0800348 return clip_simple(&ctx, &surf, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400349
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300350 /* Transformed case: use a general polygon clipping algorithm to
351 * clip the surface rectangle with each side of 'rect'.
352 * The algorithm is Sutherland-Hodgman, as explained in
353 * http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm
354 * but without looking at any of that code.
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400355 */
Sam Spilsbury619859c2013-09-13 10:01:21 +0800356 n = clip_transformed(&ctx, &surf, ex, ey);
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300357
358 if (n < 3)
359 return 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400360
361 return n;
362}
363
Derek Foremanf8180982014-10-16 16:37:02 -0500364static bool
365merge_down(pixman_box32_t *a, pixman_box32_t *b, pixman_box32_t *merge)
366{
367 if (a->x1 == b->x1 && a->x2 == b->x2 && a->y1 == b->y2) {
368 merge->x1 = a->x1;
369 merge->x2 = a->x2;
370 merge->y1 = b->y1;
371 merge->y2 = a->y2;
372 return true;
373 }
374 return false;
375}
376
377static int
378compress_bands(pixman_box32_t *inrects, int nrects,
379 pixman_box32_t **outrects)
380{
381 bool merged;
382 pixman_box32_t *out, merge_rect;
383 int i, j, nout;
384
385 if (!nrects) {
386 *outrects = NULL;
387 return 0;
388 }
389
390 /* nrects is an upper bound - we're not too worried about
391 * allocating a little extra
392 */
393 out = malloc(sizeof(pixman_box32_t) * nrects);
394 out[0] = inrects[0];
395 nout = 1;
396 for (i = 1; i < nrects; i++) {
397 for (j = 0; j < nout; j++) {
398 merged = merge_down(&inrects[i], &out[j], &merge_rect);
399 if (merged) {
400 out[j] = merge_rect;
401 break;
402 }
403 }
404 if (!merged) {
405 out[nout] = inrects[i];
406 nout++;
407 }
408 }
409 *outrects = out;
410 return nout;
411}
412
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400413static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500414texture_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400415 pixman_region32_t *surf_region)
416{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500417 struct gl_surface_state *gs = get_surface_state(ev->surface);
418 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400419 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400420 GLfloat *v, inv_width, inv_height;
421 unsigned int *vtxcnt, nvtx = 0;
422 pixman_box32_t *rects, *surf_rects;
Derek Foremanf8180982014-10-16 16:37:02 -0500423 pixman_box32_t *raw_rects;
424 int i, j, k, nrects, nsurf, raw_nrects;
425 bool used_band_compression;
426 raw_rects = pixman_region32_rectangles(region, &raw_nrects);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400427 surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
428
Derek Foremanf8180982014-10-16 16:37:02 -0500429 if (raw_nrects < 4) {
430 used_band_compression = false;
431 nrects = raw_nrects;
432 rects = raw_rects;
433 } else {
434 nrects = compress_bands(raw_rects, raw_nrects, &rects);
435 used_band_compression = true;
436 }
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400437 /* worst case we can have 8 vertices per rect (ie. clipped into
438 * an octagon):
439 */
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400440 v = wl_array_add(&gr->vertices, nrects * nsurf * 8 * 4 * sizeof *v);
441 vtxcnt = wl_array_add(&gr->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400442
Pekka Paalanen68033ac2012-12-04 15:58:15 +0200443 inv_width = 1.0 / gs->pitch;
Alexander Larsson4ea95522013-05-22 14:41:37 +0200444 inv_height = 1.0 / gs->height;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400445
446 for (i = 0; i < nrects; i++) {
447 pixman_box32_t *rect = &rects[i];
448 for (j = 0; j < nsurf; j++) {
449 pixman_box32_t *surf_rect = &surf_rects[j];
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200450 GLfloat sx, sy, bx, by;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400451 GLfloat ex[8], ey[8]; /* edge points in screen space */
452 int n;
453
454 /* The transformed surface, after clipping to the clip region,
455 * can have as many as eight sides, emitted as a triangle-fan.
456 * The first vertex in the triangle fan can be chosen arbitrarily,
457 * since the area is guaranteed to be convex.
458 *
459 * If a corner of the transformed surface falls outside of the
460 * clip region, instead of emitting one vertex for the corner
461 * of the surface, up to two are emitted for two corresponding
462 * intersection point(s) between the surface and the clip region.
463 *
464 * To do this, we first calculate the (up to eight) points that
465 * form the intersection of the clip rect and the transformed
466 * surface.
467 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500468 n = calculate_edges(ev, rect, surf_rect, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400469 if (n < 3)
470 continue;
471
472 /* emit edge points: */
473 for (k = 0; k < n; k++) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500474 weston_view_from_global_float(ev, ex[k], ey[k],
475 &sx, &sy);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400476 /* position: */
477 *(v++) = ex[k];
478 *(v++) = ey[k];
479 /* texcoord: */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500480 weston_surface_to_buffer_float(ev->surface,
481 sx, sy,
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200482 &bx, &by);
483 *(v++) = bx * inv_width;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +0400484 if (gs->y_inverted) {
485 *(v++) = by * inv_height;
486 } else {
487 *(v++) = (gs->height - by) * inv_height;
488 }
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400489 }
490
491 vtxcnt[nvtx++] = n;
492 }
493 }
494
Derek Foremanf8180982014-10-16 16:37:02 -0500495 if (used_band_compression)
496 free(rects);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400497 return nvtx;
498}
499
500static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500501triangle_fan_debug(struct weston_view *view, int first, int count)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400502{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500503 struct weston_compositor *compositor = view->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100504 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400505 int i;
506 GLushort *buffer;
507 GLushort *index;
508 int nelems;
509 static int color_idx = 0;
510 static const GLfloat color[][4] = {
511 { 1.0, 0.0, 0.0, 1.0 },
512 { 0.0, 1.0, 0.0, 1.0 },
513 { 0.0, 0.0, 1.0, 1.0 },
514 { 1.0, 1.0, 1.0, 1.0 },
515 };
516
517 nelems = (count - 1 + count - 2) * 2;
518
519 buffer = malloc(sizeof(GLushort) * nelems);
520 index = buffer;
521
522 for (i = 1; i < count; i++) {
523 *index++ = first;
524 *index++ = first + i;
525 }
526
527 for (i = 2; i < count; i++) {
528 *index++ = first + i - 1;
529 *index++ = first + i;
530 }
531
John Kåre Alsaker40684142012-11-13 19:10:25 +0100532 glUseProgram(gr->solid_shader.program);
533 glUniform4fv(gr->solid_shader.color_uniform, 1,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400534 color[color_idx++ % ARRAY_LENGTH(color)]);
535 glDrawElements(GL_LINES, nelems, GL_UNSIGNED_SHORT, buffer);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100536 glUseProgram(gr->current_shader->program);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400537 free(buffer);
538}
539
540static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500541repaint_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400542 pixman_region32_t *surf_region)
543{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500544 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400545 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400546 GLfloat *v;
547 unsigned int *vtxcnt;
548 int i, first, nfans;
549
550 /* The final region to be painted is the intersection of
551 * 'region' and 'surf_region'. However, 'region' is in the global
552 * coordinates, and 'surf_region' is in the surface-local
553 * coordinates. texture_region() will iterate over all pairs of
554 * rectangles from both regions, compute the intersection
555 * polygon for each pair, and store it as a triangle fan if
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400556 * it has a non-zero area (at least 3 vertices1, actually).
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400557 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500558 nfans = texture_region(ev, region, surf_region);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400559
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400560 v = gr->vertices.data;
561 vtxcnt = gr->vtxcnt.data;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400562
563 /* position: */
564 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
565 glEnableVertexAttribArray(0);
566
567 /* texcoord: */
568 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
569 glEnableVertexAttribArray(1);
570
571 for (i = 0, first = 0; i < nfans; i++) {
572 glDrawArrays(GL_TRIANGLE_FAN, first, vtxcnt[i]);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400573 if (gr->fan_debug)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500574 triangle_fan_debug(ev, first, vtxcnt[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400575 first += vtxcnt[i];
576 }
577
578 glDisableVertexAttribArray(1);
579 glDisableVertexAttribArray(0);
580
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400581 gr->vertices.size = 0;
582 gr->vtxcnt.size = 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400583}
584
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100585static int
586use_output(struct weston_output *output)
587{
588 static int errored;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100589 struct gl_output_state *go = get_output_state(output);
590 struct gl_renderer *gr = get_renderer(output->compositor);
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100591 EGLBoolean ret;
592
593 ret = eglMakeCurrent(gr->egl_display, go->egl_surface,
594 go->egl_surface, gr->egl_context);
595
596 if (ret == EGL_FALSE) {
597 if (errored)
598 return -1;
599 errored = 1;
600 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +0200601 gl_renderer_print_egl_error_state();
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100602 return -1;
603 }
604
605 return 0;
606}
607
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300608static int
609shader_init(struct gl_shader *shader, struct gl_renderer *gr,
610 const char *vertex_source, const char *fragment_source);
611
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400612static void
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300613use_shader(struct gl_renderer *gr, struct gl_shader *shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400614{
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300615 if (!shader->program) {
616 int ret;
617
618 ret = shader_init(shader, gr,
619 shader->vertex_source,
620 shader->fragment_source);
621
622 if (ret < 0)
623 weston_log("warning: failed to compile shader\n");
624 }
625
John Kåre Alsaker40684142012-11-13 19:10:25 +0100626 if (gr->current_shader == shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400627 return;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400628 glUseProgram(shader->program);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100629 gr->current_shader = shader;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400630}
631
632static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100633shader_uniforms(struct gl_shader *shader,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500634 struct weston_view *view,
635 struct weston_output *output)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400636{
637 int i;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500638 struct gl_surface_state *gs = get_surface_state(view->surface);
Jason Ekstrandfb23df72014-10-16 10:55:21 -0500639 struct gl_output_state *go = get_output_state(output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400640
641 glUniformMatrix4fv(shader->proj_uniform,
Jason Ekstrandfb23df72014-10-16 10:55:21 -0500642 1, GL_FALSE, go->output_matrix.d);
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100643 glUniform4fv(shader->color_uniform, 1, gs->color);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500644 glUniform1f(shader->alpha_uniform, view->alpha);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400645
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100646 for (i = 0; i < gs->num_textures; i++)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400647 glUniform1i(shader->tex_uniforms[i], i);
648}
649
650static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500651draw_view(struct weston_view *ev, struct weston_output *output,
652 pixman_region32_t *damage) /* in global coordinates */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400653{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500654 struct weston_compositor *ec = ev->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100655 struct gl_renderer *gr = get_renderer(ec);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500656 struct gl_surface_state *gs = get_surface_state(ev->surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400657 /* repaint bounding region in global coordinates: */
658 pixman_region32_t repaint;
Pekka Paalanenfa79b1d2015-02-18 09:48:59 +0200659 /* opaque region in surface coordinates: */
660 pixman_region32_t surface_opaque;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400661 /* non-opaque region in surface coordinates: */
662 pixman_region32_t surface_blend;
663 GLint filter;
664 int i;
665
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +0200666 /* In case of a runtime switch of renderers, we may not have received
667 * an attach for this surface since the switch. In that case we don't
668 * have a valid buffer or a proper shader set up so skip rendering. */
669 if (!gs->shader)
670 return;
671
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400672 pixman_region32_init(&repaint);
673 pixman_region32_intersect(&repaint,
Pekka Paalanen25c0ca52015-02-19 11:15:33 +0200674 &ev->transform.boundingbox, damage);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500675 pixman_region32_subtract(&repaint, &repaint, &ev->clip);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400676
677 if (!pixman_region32_not_empty(&repaint))
678 goto out;
679
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400680 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
681
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400682 if (gr->fan_debug) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100683 use_shader(gr, &gr->solid_shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500684 shader_uniforms(&gr->solid_shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400685 }
686
John Kåre Alsaker40684142012-11-13 19:10:25 +0100687 use_shader(gr, gs->shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500688 shader_uniforms(gs->shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400689
Jason Ekstranda7af7042013-10-12 22:38:11 -0500690 if (ev->transform.enabled || output->zoom.active ||
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200691 output->current_scale != ev->surface->buffer_viewport.buffer.scale)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400692 filter = GL_LINEAR;
693 else
694 filter = GL_NEAREST;
695
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100696 for (i = 0; i < gs->num_textures; i++) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400697 glActiveTexture(GL_TEXTURE0 + i);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100698 glBindTexture(gs->target, gs->textures[i]);
699 glTexParameteri(gs->target, GL_TEXTURE_MIN_FILTER, filter);
700 glTexParameteri(gs->target, GL_TEXTURE_MAG_FILTER, filter);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400701 }
702
703 /* blended region is whole surface minus opaque region: */
704 pixman_region32_init_rect(&surface_blend, 0, 0,
Jason Ekstrand918f2dd2013-12-02 21:01:53 -0600705 ev->surface->width, ev->surface->height);
Pekka Paalanenfa79b1d2015-02-18 09:48:59 +0200706 if (ev->geometry.scissor_enabled)
707 pixman_region32_intersect(&surface_blend, &surface_blend,
708 &ev->geometry.scissor);
709 pixman_region32_subtract(&surface_blend, &surface_blend,
710 &ev->surface->opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400711
Jason Ekstranda7af7042013-10-12 22:38:11 -0500712 /* XXX: Should we be using ev->transform.opaque here? */
Pekka Paalanenfa79b1d2015-02-18 09:48:59 +0200713 pixman_region32_init(&surface_opaque);
714 if (ev->geometry.scissor_enabled)
715 pixman_region32_intersect(&surface_opaque,
716 &ev->surface->opaque,
717 &ev->geometry.scissor);
718 else
719 pixman_region32_copy(&surface_opaque, &ev->surface->opaque);
720
721 if (pixman_region32_not_empty(&surface_opaque)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100722 if (gs->shader == &gr->texture_shader_rgba) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400723 /* Special case for RGBA textures with possibly
724 * bad data in alpha channel: use the shader
725 * that forces texture alpha = 1.0.
726 * Xwayland surfaces need this.
727 */
John Kåre Alsaker40684142012-11-13 19:10:25 +0100728 use_shader(gr, &gr->texture_shader_rgbx);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500729 shader_uniforms(&gr->texture_shader_rgbx, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400730 }
731
Jason Ekstranda7af7042013-10-12 22:38:11 -0500732 if (ev->alpha < 1.0)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400733 glEnable(GL_BLEND);
734 else
735 glDisable(GL_BLEND);
736
Pekka Paalanenfa79b1d2015-02-18 09:48:59 +0200737 repaint_region(ev, &repaint, &surface_opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400738 }
739
740 if (pixman_region32_not_empty(&surface_blend)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100741 use_shader(gr, gs->shader);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400742 glEnable(GL_BLEND);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500743 repaint_region(ev, &repaint, &surface_blend);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400744 }
745
746 pixman_region32_fini(&surface_blend);
Pekka Paalanenfa79b1d2015-02-18 09:48:59 +0200747 pixman_region32_fini(&surface_opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400748
749out:
750 pixman_region32_fini(&repaint);
751}
752
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400753static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500754repaint_views(struct weston_output *output, pixman_region32_t *damage)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400755{
756 struct weston_compositor *compositor = output->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500757 struct weston_view *view;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400758
Jason Ekstranda7af7042013-10-12 22:38:11 -0500759 wl_list_for_each_reverse(view, &compositor->view_list, link)
760 if (view->plane == &compositor->primary_plane)
761 draw_view(view, output, damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400762}
763
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500764static void
Jason Ekstrande5512d42014-02-04 21:36:38 -0600765draw_output_border_texture(struct gl_output_state *go,
766 enum gl_renderer_border_side side,
767 int32_t x, int32_t y,
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500768 int32_t width, int32_t height)
769{
Jason Ekstrande5512d42014-02-04 21:36:38 -0600770 struct gl_border_image *img = &go->borders[side];
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500771 static GLushort indices [] = { 0, 1, 3, 3, 1, 2 };
772
773 if (!img->data) {
774 if (img->tex) {
775 glDeleteTextures(1, &img->tex);
776 img->tex = 0;
777 }
778
779 return;
780 }
781
782 if (!img->tex) {
783 glGenTextures(1, &img->tex);
784 glBindTexture(GL_TEXTURE_2D, img->tex);
785
786 glTexParameteri(GL_TEXTURE_2D,
787 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
788 glTexParameteri(GL_TEXTURE_2D,
789 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
790 glTexParameteri(GL_TEXTURE_2D,
791 GL_TEXTURE_MIN_FILTER, GL_NEAREST);
792 glTexParameteri(GL_TEXTURE_2D,
793 GL_TEXTURE_MAG_FILTER, GL_NEAREST);
794 } else {
795 glBindTexture(GL_TEXTURE_2D, img->tex);
796 }
797
Jason Ekstrande5512d42014-02-04 21:36:38 -0600798 if (go->border_status & (1 << side)) {
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500799#ifdef GL_EXT_unpack_subimage
800 glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0);
801 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
802 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
803#endif
804 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
805 img->tex_width, img->height, 0,
806 GL_BGRA_EXT, GL_UNSIGNED_BYTE, img->data);
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500807 }
808
809 GLfloat texcoord[] = {
810 0.0f, 0.0f,
811 (GLfloat)img->width / (GLfloat)img->tex_width, 0.0f,
812 (GLfloat)img->width / (GLfloat)img->tex_width, 1.0f,
813 0.0f, 1.0f,
814 };
815
816 GLfloat verts[] = {
817 x, y,
818 x + width, y,
819 x + width, y + height,
820 x, y + height
821 };
822
823 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
824 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord);
825 glEnableVertexAttribArray(0);
826 glEnableVertexAttribArray(1);
827
828 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
829
830 glDisableVertexAttribArray(1);
831 glDisableVertexAttribArray(0);
832}
833
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -0600834static int
835output_has_borders(struct weston_output *output)
836{
837 struct gl_output_state *go = get_output_state(output);
838
839 return go->borders[GL_RENDERER_BORDER_TOP].data ||
840 go->borders[GL_RENDERER_BORDER_RIGHT].data ||
841 go->borders[GL_RENDERER_BORDER_BOTTOM].data ||
842 go->borders[GL_RENDERER_BORDER_LEFT].data;
843}
844
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500845static void
Jason Ekstrande5512d42014-02-04 21:36:38 -0600846draw_output_borders(struct weston_output *output,
847 enum gl_border_status border_status)
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500848{
849 struct gl_output_state *go = get_output_state(output);
850 struct gl_renderer *gr = get_renderer(output->compositor);
851 struct gl_shader *shader = &gr->texture_shader_rgba;
Jason Ekstrand00b84282013-10-27 22:24:59 -0500852 struct gl_border_image *top, *bottom, *left, *right;
853 struct weston_matrix matrix;
854 int full_width, full_height;
855
Jason Ekstrande5512d42014-02-04 21:36:38 -0600856 if (border_status == BORDER_STATUS_CLEAN)
857 return; /* Clean. Nothing to do. */
858
Jason Ekstrand00b84282013-10-27 22:24:59 -0500859 top = &go->borders[GL_RENDERER_BORDER_TOP];
860 bottom = &go->borders[GL_RENDERER_BORDER_BOTTOM];
861 left = &go->borders[GL_RENDERER_BORDER_LEFT];
862 right = &go->borders[GL_RENDERER_BORDER_RIGHT];
863
864 full_width = output->current_mode->width + left->width + right->width;
865 full_height = output->current_mode->height + top->height + bottom->height;
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500866
867 glDisable(GL_BLEND);
868 use_shader(gr, shader);
869
Jason Ekstrand00b84282013-10-27 22:24:59 -0500870 glViewport(0, 0, full_width, full_height);
871
872 weston_matrix_init(&matrix);
873 weston_matrix_translate(&matrix, -full_width/2.0, -full_height/2.0, 0);
874 weston_matrix_scale(&matrix, 2.0/full_width, -2.0/full_height, 1);
875 glUniformMatrix4fv(shader->proj_uniform, 1, GL_FALSE, matrix.d);
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500876
877 glUniform1i(shader->tex_uniforms[0], 0);
878 glUniform1f(shader->alpha_uniform, 1);
879 glActiveTexture(GL_TEXTURE0);
880
Jason Ekstrande5512d42014-02-04 21:36:38 -0600881 if (border_status & BORDER_TOP_DIRTY)
882 draw_output_border_texture(go, GL_RENDERER_BORDER_TOP,
883 0, 0,
884 full_width, top->height);
885 if (border_status & BORDER_LEFT_DIRTY)
886 draw_output_border_texture(go, GL_RENDERER_BORDER_LEFT,
887 0, top->height,
888 left->width, output->current_mode->height);
889 if (border_status & BORDER_RIGHT_DIRTY)
890 draw_output_border_texture(go, GL_RENDERER_BORDER_RIGHT,
891 full_width - right->width, top->height,
892 right->width, output->current_mode->height);
893 if (border_status & BORDER_BOTTOM_DIRTY)
894 draw_output_border_texture(go, GL_RENDERER_BORDER_BOTTOM,
895 0, full_height - bottom->height,
896 full_width, bottom->height);
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500897}
John Kåre Alsaker44154502012-11-13 19:10:20 +0100898
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400899static void
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -0600900output_get_border_damage(struct weston_output *output,
901 enum gl_border_status border_status,
902 pixman_region32_t *damage)
903{
904 struct gl_output_state *go = get_output_state(output);
905 struct gl_border_image *top, *bottom, *left, *right;
906 int full_width, full_height;
907
908 if (border_status == BORDER_STATUS_CLEAN)
909 return; /* Clean. Nothing to do. */
910
911 top = &go->borders[GL_RENDERER_BORDER_TOP];
912 bottom = &go->borders[GL_RENDERER_BORDER_BOTTOM];
913 left = &go->borders[GL_RENDERER_BORDER_LEFT];
914 right = &go->borders[GL_RENDERER_BORDER_RIGHT];
915
916 full_width = output->current_mode->width + left->width + right->width;
917 full_height = output->current_mode->height + top->height + bottom->height;
918 if (border_status & BORDER_TOP_DIRTY)
919 pixman_region32_union_rect(damage, damage,
920 0, 0,
921 full_width, top->height);
922 if (border_status & BORDER_LEFT_DIRTY)
923 pixman_region32_union_rect(damage, damage,
924 0, top->height,
925 left->width, output->current_mode->height);
926 if (border_status & BORDER_RIGHT_DIRTY)
927 pixman_region32_union_rect(damage, damage,
928 full_width - right->width, top->height,
929 right->width, output->current_mode->height);
930 if (border_status & BORDER_BOTTOM_DIRTY)
931 pixman_region32_union_rect(damage, damage,
932 0, full_height - bottom->height,
933 full_width, bottom->height);
934}
935
936static void
Jason Ekstrande5512d42014-02-04 21:36:38 -0600937output_get_damage(struct weston_output *output,
938 pixman_region32_t *buffer_damage, uint32_t *border_damage)
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200939{
940 struct gl_output_state *go = get_output_state(output);
941 struct gl_renderer *gr = get_renderer(output->compositor);
942 EGLint buffer_age = 0;
943 EGLBoolean ret;
944 int i;
945
946 if (gr->has_egl_buffer_age) {
947 ret = eglQuerySurface(gr->egl_display, go->egl_surface,
948 EGL_BUFFER_AGE_EXT, &buffer_age);
949 if (ret == EGL_FALSE) {
950 weston_log("buffer age query failed.\n");
951 gl_renderer_print_egl_error_state();
952 }
953 }
954
Jason Ekstrande5512d42014-02-04 21:36:38 -0600955 if (buffer_age == 0 || buffer_age - 1 > BUFFER_DAMAGE_COUNT) {
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200956 pixman_region32_copy(buffer_damage, &output->region);
Jason Ekstrande5512d42014-02-04 21:36:38 -0600957 *border_damage = BORDER_ALL_DIRTY;
958 } else {
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200959 for (i = 0; i < buffer_age - 1; i++)
Derek Foreman4c582662014-10-09 18:39:44 -0500960 *border_damage |= go->border_damage[(go->buffer_damage_index + i) % BUFFER_DAMAGE_COUNT];
Jason Ekstrande5512d42014-02-04 21:36:38 -0600961
962 if (*border_damage & BORDER_SIZE_CHANGED) {
963 /* If we've had a resize, we have to do a full
964 * repaint. */
965 *border_damage |= BORDER_ALL_DIRTY;
966 pixman_region32_copy(buffer_damage, &output->region);
967 } else {
968 for (i = 0; i < buffer_age - 1; i++)
969 pixman_region32_union(buffer_damage,
970 buffer_damage,
Derek Foreman4c582662014-10-09 18:39:44 -0500971 &go->buffer_damage[(go->buffer_damage_index + i) % BUFFER_DAMAGE_COUNT]);
Jason Ekstrande5512d42014-02-04 21:36:38 -0600972 }
973 }
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200974}
975
976static void
977output_rotate_damage(struct weston_output *output,
Jason Ekstrande5512d42014-02-04 21:36:38 -0600978 pixman_region32_t *output_damage,
979 enum gl_border_status border_status)
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200980{
981 struct gl_output_state *go = get_output_state(output);
982 struct gl_renderer *gr = get_renderer(output->compositor);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200983
984 if (!gr->has_egl_buffer_age)
985 return;
986
Derek Foreman4c582662014-10-09 18:39:44 -0500987 go->buffer_damage_index += BUFFER_DAMAGE_COUNT - 1;
988 go->buffer_damage_index %= BUFFER_DAMAGE_COUNT;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200989
Derek Foreman4c582662014-10-09 18:39:44 -0500990 pixman_region32_copy(&go->buffer_damage[go->buffer_damage_index], output_damage);
991 go->border_damage[go->buffer_damage_index] = border_status;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200992}
993
Derek Foremanc4cfe852015-05-15 12:12:40 -0500994/* NOTE: We now allow falling back to ARGB gl visuals when XRGB is
995 * unavailable, so we're assuming the background has no transparency
996 * and that everything with a blend, like drop shadows, will have something
997 * opaque (like the background) drawn underneath it.
998 *
999 * Depending on the underlying hardware, violating that assumption could
1000 * result in seeing through to another display plane.
1001 */
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001002static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001003gl_renderer_repaint_output(struct weston_output *output,
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001004 pixman_region32_t *output_damage)
1005{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001006 struct gl_output_state *go = get_output_state(output);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001007 struct weston_compositor *compositor = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001008 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001009 EGLBoolean ret;
1010 static int errored;
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -06001011#ifdef EGL_EXT_swap_buffers_with_damage
1012 int i, nrects, buffer_height;
1013 EGLint *egl_damage, *d;
1014 pixman_box32_t *rects;
1015#endif
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001016 pixman_region32_t buffer_damage, total_damage;
Jason Ekstrande5512d42014-02-04 21:36:38 -06001017 enum gl_border_status border_damage = BORDER_STATUS_CLEAN;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001018
Jason Ekstrandae0c6e32014-10-16 10:55:20 -05001019 if (use_output(output) < 0)
1020 return;
1021
Jason Ekstrand00b84282013-10-27 22:24:59 -05001022 /* Calculate the viewport */
1023 glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width,
1024 go->borders[GL_RENDERER_BORDER_BOTTOM].height,
1025 output->current_mode->width,
1026 output->current_mode->height);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001027
Jason Ekstrandfb23df72014-10-16 10:55:21 -05001028 /* Calculate the global GL matrix */
1029 go->output_matrix = output->matrix;
1030 weston_matrix_translate(&go->output_matrix,
1031 -(output->current_mode->width / 2.0),
1032 -(output->current_mode->height / 2.0), 0);
1033 weston_matrix_scale(&go->output_matrix,
1034 2.0 / output->current_mode->width,
1035 -2.0 / output->current_mode->height, 1);
1036
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001037 /* if debugging, redraw everything outside the damage to clean up
1038 * debug lines from the previous draw on this buffer:
1039 */
Kristian Høgsberg8799d412013-05-07 10:50:09 -04001040 if (gr->fan_debug) {
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001041 pixman_region32_t undamaged;
1042 pixman_region32_init(&undamaged);
1043 pixman_region32_subtract(&undamaged, &output->region,
1044 output_damage);
Kristian Høgsberg8799d412013-05-07 10:50:09 -04001045 gr->fan_debug = 0;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001046 repaint_views(output, &undamaged);
Kristian Høgsberg8799d412013-05-07 10:50:09 -04001047 gr->fan_debug = 1;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001048 pixman_region32_fini(&undamaged);
1049 }
1050
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +02001051 pixman_region32_init(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001052 pixman_region32_init(&buffer_damage);
1053
Jason Ekstrande5512d42014-02-04 21:36:38 -06001054 output_get_damage(output, &buffer_damage, &border_damage);
1055 output_rotate_damage(output, output_damage, go->border_status);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001056
1057 pixman_region32_union(&total_damage, &buffer_damage, output_damage);
Jason Ekstrande5512d42014-02-04 21:36:38 -06001058 border_damage |= go->border_status;
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +03001059
Jason Ekstranda7af7042013-10-12 22:38:11 -05001060 repaint_views(output, &total_damage);
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +02001061
1062 pixman_region32_fini(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001063 pixman_region32_fini(&buffer_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001064
Jason Ekstrande5512d42014-02-04 21:36:38 -06001065 draw_output_borders(output, border_damage);
John Kåre Alsaker44154502012-11-13 19:10:20 +01001066
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001067 pixman_region32_copy(&output->previous_damage, output_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001068 wl_signal_emit(&output->frame_signal, output);
1069
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -06001070#ifdef EGL_EXT_swap_buffers_with_damage
1071 if (gr->swap_buffers_with_damage) {
1072 pixman_region32_init(&buffer_damage);
1073 weston_transformed_region(output->width, output->height,
1074 output->transform,
1075 output->current_scale,
1076 output_damage, &buffer_damage);
1077
1078 if (output_has_borders(output)) {
1079 pixman_region32_translate(&buffer_damage,
1080 go->borders[GL_RENDERER_BORDER_LEFT].width,
1081 go->borders[GL_RENDERER_BORDER_TOP].height);
1082 output_get_border_damage(output, go->border_status,
1083 &buffer_damage);
1084 }
1085
1086 rects = pixman_region32_rectangles(&buffer_damage, &nrects);
1087 egl_damage = malloc(nrects * 4 * sizeof(EGLint));
1088
1089 buffer_height = go->borders[GL_RENDERER_BORDER_TOP].height +
1090 output->current_mode->height +
1091 go->borders[GL_RENDERER_BORDER_BOTTOM].height;
1092
1093 d = egl_damage;
1094 for (i = 0; i < nrects; ++i) {
1095 *d++ = rects[i].x1;
1096 *d++ = buffer_height - rects[i].y2;
1097 *d++ = rects[i].x2 - rects[i].x1;
1098 *d++ = rects[i].y2 - rects[i].y1;
1099 }
1100 ret = gr->swap_buffers_with_damage(gr->egl_display,
1101 go->egl_surface,
1102 egl_damage, nrects);
1103 free(egl_damage);
1104 pixman_region32_fini(&buffer_damage);
1105 } else {
1106 ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
1107 }
1108#else /* ! defined EGL_EXT_swap_buffers_with_damage */
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001109 ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -06001110#endif
1111
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001112 if (ret == EGL_FALSE && !errored) {
1113 errored = 1;
1114 weston_log("Failed in eglSwapBuffers.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001115 gl_renderer_print_egl_error_state();
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001116 }
1117
Jason Ekstrande5512d42014-02-04 21:36:38 -06001118 go->border_status = BORDER_STATUS_CLEAN;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001119}
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001120
John Kåre Alsakera95b2d62012-11-13 19:10:21 +01001121static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001122gl_renderer_read_pixels(struct weston_output *output,
John Kåre Alsakera95b2d62012-11-13 19:10:21 +01001123 pixman_format_code_t format, void *pixels,
1124 uint32_t x, uint32_t y,
1125 uint32_t width, uint32_t height)
1126{
1127 GLenum gl_format;
Jason Ekstrand701f6362014-04-02 19:53:59 -05001128 struct gl_output_state *go = get_output_state(output);
1129
1130 x += go->borders[GL_RENDERER_BORDER_LEFT].width;
1131 y += go->borders[GL_RENDERER_BORDER_BOTTOM].height;
John Kåre Alsakera95b2d62012-11-13 19:10:21 +01001132
1133 switch (format) {
1134 case PIXMAN_a8r8g8b8:
1135 gl_format = GL_BGRA_EXT;
1136 break;
1137 case PIXMAN_a8b8g8r8:
1138 gl_format = GL_RGBA;
1139 break;
1140 default:
1141 return -1;
1142 }
1143
1144 if (use_output(output) < 0)
1145 return -1;
1146
1147 glPixelStorei(GL_PACK_ALIGNMENT, 1);
1148 glReadPixels(x, y, width, height, gl_format,
1149 GL_UNSIGNED_BYTE, pixels);
1150
1151 return 0;
1152}
1153
Kristian Høgsbergfa1be022012-09-05 22:49:55 -04001154static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001155gl_renderer_flush_damage(struct weston_surface *surface)
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001156{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001157 struct gl_renderer *gr = get_renderer(surface->compositor);
1158 struct gl_surface_state *gs = get_surface_state(surface);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001159 struct weston_buffer *buffer = gs->buffer_ref.buffer;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001160 struct weston_view *view;
1161 int texture_used;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001162
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -07001163#ifdef GL_EXT_unpack_subimage
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001164 pixman_box32_t *rectangles;
1165 void *data;
1166 int i, n;
1167#endif
1168
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001169 pixman_region32_union(&gs->texture_damage,
1170 &gs->texture_damage, &surface->damage);
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001171
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001172 if (!buffer)
1173 return;
1174
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001175 /* Avoid upload, if the texture won't be used this time.
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001176 * We still accumulate the damage in texture_damage, and
1177 * hold the reference to the buffer, in case the surface
1178 * migrates back to the primary plane.
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001179 */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001180 texture_used = 0;
1181 wl_list_for_each(view, &surface->views, surface_link) {
1182 if (view->plane == &surface->compositor->primary_plane) {
1183 texture_used = 1;
1184 break;
1185 }
1186 }
1187 if (!texture_used)
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001188 return;
1189
Ander Conselvan de Oliveira895b1fd2013-11-19 15:22:05 +02001190 if (!pixman_region32_not_empty(&gs->texture_damage) &&
1191 !gs->needs_full_upload)
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001192 goto done;
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001193
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001194 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001195
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001196 if (!gr->has_unpack_subimage) {
Neil Robertse5051712013-11-13 15:44:06 +00001197 wl_shm_buffer_begin_access(buffer->shm_buffer);
Neil Roberts4d085e72014-04-07 15:01:01 +01001198 glTexImage2D(GL_TEXTURE_2D, 0, gs->gl_format,
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001199 gs->pitch, buffer->height, 0,
Neil Roberts4d085e72014-04-07 15:01:01 +01001200 gs->gl_format, gs->gl_pixel_type,
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001201 wl_shm_buffer_get_data(buffer->shm_buffer));
Neil Robertse5051712013-11-13 15:44:06 +00001202 wl_shm_buffer_end_access(buffer->shm_buffer);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001203
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001204 goto done;
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001205 }
1206
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -07001207#ifdef GL_EXT_unpack_subimage
1208 glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, gs->pitch);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001209 data = wl_shm_buffer_get_data(buffer->shm_buffer);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +03001210
1211 if (gs->needs_full_upload) {
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -07001212 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
1213 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
Neil Robertse5051712013-11-13 15:44:06 +00001214 wl_shm_buffer_begin_access(buffer->shm_buffer);
Neil Roberts4d085e72014-04-07 15:01:01 +01001215 glTexImage2D(GL_TEXTURE_2D, 0, gs->gl_format,
Neil Roberts39a443f2014-04-04 16:24:54 +01001216 gs->pitch, buffer->height, 0,
Neil Roberts4d085e72014-04-07 15:01:01 +01001217 gs->gl_format, gs->gl_pixel_type, data);
Neil Robertse5051712013-11-13 15:44:06 +00001218 wl_shm_buffer_end_access(buffer->shm_buffer);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +03001219 goto done;
1220 }
1221
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001222 rectangles = pixman_region32_rectangles(&gs->texture_damage, &n);
Neil Robertse5051712013-11-13 15:44:06 +00001223 wl_shm_buffer_begin_access(buffer->shm_buffer);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001224 for (i = 0; i < n; i++) {
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +02001225 pixman_box32_t r;
1226
1227 r = weston_surface_to_buffer_rect(surface, rectangles[i]);
1228
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -07001229 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, r.x1);
1230 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, r.y1);
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +02001231 glTexSubImage2D(GL_TEXTURE_2D, 0, r.x1, r.y1,
1232 r.x2 - r.x1, r.y2 - r.y1,
Neil Roberts4d085e72014-04-07 15:01:01 +01001233 gs->gl_format, gs->gl_pixel_type, data);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001234 }
Neil Robertse5051712013-11-13 15:44:06 +00001235 wl_shm_buffer_end_access(buffer->shm_buffer);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001236#endif
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001237
1238done:
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001239 pixman_region32_fini(&gs->texture_damage);
1240 pixman_region32_init(&gs->texture_damage);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +03001241 gs->needs_full_upload = 0;
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001242
1243 weston_buffer_reference(&gs->buffer_ref, NULL);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001244}
1245
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001246static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001247ensure_textures(struct gl_surface_state *gs, int num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001248{
1249 int i;
1250
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001251 if (num_textures <= gs->num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001252 return;
1253
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001254 for (i = gs->num_textures; i < num_textures; i++) {
1255 glGenTextures(1, &gs->textures[i]);
1256 glBindTexture(gs->target, gs->textures[i]);
1257 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001258 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001259 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001260 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1261 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001262 gs->num_textures = num_textures;
1263 glBindTexture(gs->target, 0);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001264}
1265
Kristian Høgsbergfa1be022012-09-05 22:49:55 -04001266static void
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001267gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
1268 struct wl_shm_buffer *shm_buffer)
1269{
1270 struct weston_compositor *ec = es->compositor;
1271 struct gl_renderer *gr = get_renderer(ec);
1272 struct gl_surface_state *gs = get_surface_state(es);
Neil Roberts4d085e72014-04-07 15:01:01 +01001273 GLenum gl_format, gl_pixel_type;
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001274 int pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001275
1276 buffer->shm_buffer = shm_buffer;
1277 buffer->width = wl_shm_buffer_get_width(shm_buffer);
1278 buffer->height = wl_shm_buffer_get_height(shm_buffer);
1279
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001280 switch (wl_shm_buffer_get_format(shm_buffer)) {
1281 case WL_SHM_FORMAT_XRGB8888:
1282 gs->shader = &gr->texture_shader_rgbx;
1283 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
Neil Roberts4d085e72014-04-07 15:01:01 +01001284 gl_format = GL_BGRA_EXT;
1285 gl_pixel_type = GL_UNSIGNED_BYTE;
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001286 break;
1287 case WL_SHM_FORMAT_ARGB8888:
1288 gs->shader = &gr->texture_shader_rgba;
1289 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
Neil Roberts4d085e72014-04-07 15:01:01 +01001290 gl_format = GL_BGRA_EXT;
1291 gl_pixel_type = GL_UNSIGNED_BYTE;
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001292 break;
1293 case WL_SHM_FORMAT_RGB565:
1294 gs->shader = &gr->texture_shader_rgbx;
1295 pitch = wl_shm_buffer_get_stride(shm_buffer) / 2;
Neil Roberts4d085e72014-04-07 15:01:01 +01001296 gl_format = GL_RGB;
1297 gl_pixel_type = GL_UNSIGNED_SHORT_5_6_5;
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001298 break;
1299 default:
Neil Roberts4d085e72014-04-07 15:01:01 +01001300 weston_log("warning: unknown shm buffer format: %08x\n",
1301 wl_shm_buffer_get_format(shm_buffer));
1302 return;
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001303 }
1304
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001305 /* Only allocate a texture if it doesn't match existing one.
1306 * If a switch from DRM allocated buffer to a SHM buffer is
1307 * happening, we need to allocate a new texture buffer. */
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001308 if (pitch != gs->pitch ||
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001309 buffer->height != gs->height ||
Neil Roberts4d085e72014-04-07 15:01:01 +01001310 gl_format != gs->gl_format ||
1311 gl_pixel_type != gs->gl_pixel_type ||
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001312 gs->buffer_type != BUFFER_TYPE_SHM) {
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001313 gs->pitch = pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001314 gs->height = buffer->height;
1315 gs->target = GL_TEXTURE_2D;
Neil Roberts4d085e72014-04-07 15:01:01 +01001316 gs->gl_format = gl_format;
1317 gs->gl_pixel_type = gl_pixel_type;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001318 gs->buffer_type = BUFFER_TYPE_SHM;
1319 gs->needs_full_upload = 1;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001320 gs->y_inverted = 1;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001321
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001322 gs->surface = es;
1323
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001324 ensure_textures(gs, 1);
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001325 }
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001326}
1327
1328static void
1329gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
1330 uint32_t format)
1331{
1332 struct weston_compositor *ec = es->compositor;
1333 struct gl_renderer *gr = get_renderer(ec);
1334 struct gl_surface_state *gs = get_surface_state(es);
1335 EGLint attribs[3];
1336 int i, num_planes;
1337
1338 buffer->legacy_buffer = (struct wl_buffer *)buffer->resource;
1339 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1340 EGL_WIDTH, &buffer->width);
1341 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1342 EGL_HEIGHT, &buffer->height);
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001343 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1344 EGL_WAYLAND_Y_INVERTED_WL, &buffer->y_inverted);
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001345
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +03001346 for (i = 0; i < gs->num_images; i++) {
1347 egl_image_unref(gs->images[i]);
1348 gs->images[i] = NULL;
1349 }
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001350 gs->num_images = 0;
1351 gs->target = GL_TEXTURE_2D;
1352 switch (format) {
1353 case EGL_TEXTURE_RGB:
1354 case EGL_TEXTURE_RGBA:
1355 default:
1356 num_planes = 1;
1357 gs->shader = &gr->texture_shader_rgba;
1358 break;
1359 case EGL_TEXTURE_EXTERNAL_WL:
1360 num_planes = 1;
1361 gs->target = GL_TEXTURE_EXTERNAL_OES;
1362 gs->shader = &gr->texture_shader_egl_external;
1363 break;
1364 case EGL_TEXTURE_Y_UV_WL:
1365 num_planes = 2;
1366 gs->shader = &gr->texture_shader_y_uv;
1367 break;
1368 case EGL_TEXTURE_Y_U_V_WL:
1369 num_planes = 3;
1370 gs->shader = &gr->texture_shader_y_u_v;
1371 break;
1372 case EGL_TEXTURE_Y_XUXV_WL:
1373 num_planes = 2;
1374 gs->shader = &gr->texture_shader_y_xuxv;
1375 break;
1376 }
1377
1378 ensure_textures(gs, num_planes);
1379 for (i = 0; i < num_planes; i++) {
1380 attribs[0] = EGL_WAYLAND_PLANE_WL;
1381 attribs[1] = i;
1382 attribs[2] = EGL_NONE;
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +03001383 gs->images[i] = egl_image_create(gr,
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001384 EGL_WAYLAND_BUFFER_WL,
1385 buffer->legacy_buffer,
1386 attribs);
1387 if (!gs->images[i]) {
1388 weston_log("failed to create img for plane %d\n", i);
1389 continue;
1390 }
1391 gs->num_images++;
1392
1393 glActiveTexture(GL_TEXTURE0 + i);
1394 glBindTexture(gs->target, gs->textures[i]);
1395 gr->image_target_texture_2d(gs->target,
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +03001396 gs->images[i]->image);
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001397 }
1398
1399 gs->pitch = buffer->width;
1400 gs->height = buffer->height;
1401 gs->buffer_type = BUFFER_TYPE_EGL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001402 gs->y_inverted = buffer->y_inverted;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001403}
1404
1405static void
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001406gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001407{
1408 struct weston_compositor *ec = es->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001409 struct gl_renderer *gr = get_renderer(ec);
1410 struct gl_surface_state *gs = get_surface_state(es);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001411 struct wl_shm_buffer *shm_buffer;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001412 EGLint format;
1413 int i;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001414
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001415 weston_buffer_reference(&gs->buffer_ref, buffer);
1416
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001417 if (!buffer) {
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001418 for (i = 0; i < gs->num_images; i++) {
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +03001419 egl_image_unref(gs->images[i]);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001420 gs->images[i] = NULL;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001421 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001422 gs->num_images = 0;
1423 glDeleteTextures(gs->num_textures, gs->textures);
1424 gs->num_textures = 0;
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001425 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001426 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001427 return;
1428 }
1429
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001430 shm_buffer = wl_shm_buffer_get(buffer->resource);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001431
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001432 if (shm_buffer)
1433 gl_renderer_attach_shm(es, buffer, shm_buffer);
Kristian Høgsberg47229392013-08-07 11:59:54 -07001434 else if (gr->query_buffer(gr->egl_display, (void *) buffer->resource,
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001435 EGL_TEXTURE_FORMAT, &format))
1436 gl_renderer_attach_egl(es, buffer, format);
1437 else {
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001438 weston_log("unhandled buffer type!\n");
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001439 weston_buffer_reference(&gs->buffer_ref, NULL);
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001440 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001441 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001442 }
1443}
1444
Kristian Høgsberg42263852012-09-06 21:59:29 -04001445static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001446gl_renderer_surface_set_color(struct weston_surface *surface,
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001447 float red, float green, float blue, float alpha)
1448{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001449 struct gl_surface_state *gs = get_surface_state(surface);
1450 struct gl_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001451
1452 gs->color[0] = red;
1453 gs->color[1] = green;
1454 gs->color[2] = blue;
1455 gs->color[3] = alpha;
Pekka Paalanenaeb917e2015-02-09 13:56:56 +02001456 gs->buffer_type = BUFFER_TYPE_SOLID;
1457 gs->pitch = 1;
1458 gs->height = 1;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001459
John Kåre Alsaker40684142012-11-13 19:10:25 +01001460 gs->shader = &gr->solid_shader;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001461}
1462
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001463static void
Pekka Paalaneneb35cbe2015-02-09 13:37:27 +02001464gl_renderer_surface_get_content_size(struct weston_surface *surface,
1465 int *width, int *height)
1466{
1467 struct gl_surface_state *gs = get_surface_state(surface);
1468
1469 if (gs->buffer_type == BUFFER_TYPE_NULL) {
1470 *width = 0;
1471 *height = 0;
1472 } else {
1473 *width = gs->pitch;
1474 *height = gs->height;
1475 }
1476}
1477
1478static uint32_t
1479pack_color(pixman_format_code_t format, float *c)
1480{
1481 uint8_t r = round(c[0] * 255.0f);
1482 uint8_t g = round(c[1] * 255.0f);
1483 uint8_t b = round(c[2] * 255.0f);
1484 uint8_t a = round(c[3] * 255.0f);
1485
1486 switch (format) {
1487 case PIXMAN_a8b8g8r8:
1488 return (a << 24) | (b << 16) | (g << 8) | r;
1489 default:
1490 assert(0);
1491 return 0;
1492 }
1493}
1494
1495static int
1496gl_renderer_surface_copy_content(struct weston_surface *surface,
1497 void *target, size_t size,
1498 int src_x, int src_y,
1499 int width, int height)
1500{
1501 static const GLfloat verts[4 * 2] = {
1502 0.0f, 0.0f,
1503 1.0f, 0.0f,
1504 1.0f, 1.0f,
1505 0.0f, 1.0f
1506 };
1507 static const GLfloat projmat_normal[16] = { /* transpose */
1508 2.0f, 0.0f, 0.0f, 0.0f,
1509 0.0f, 2.0f, 0.0f, 0.0f,
1510 0.0f, 0.0f, 1.0f, 0.0f,
1511 -1.0f, -1.0f, 0.0f, 1.0f
1512 };
1513 static const GLfloat projmat_yinvert[16] = { /* transpose */
1514 2.0f, 0.0f, 0.0f, 0.0f,
1515 0.0f, -2.0f, 0.0f, 0.0f,
1516 0.0f, 0.0f, 1.0f, 0.0f,
1517 -1.0f, 1.0f, 0.0f, 1.0f
1518 };
1519 const pixman_format_code_t format = PIXMAN_a8b8g8r8;
1520 const size_t bytespp = 4; /* PIXMAN_a8b8g8r8 */
1521 const GLenum gl_format = GL_RGBA; /* PIXMAN_a8b8g8r8 little-endian */
1522 struct gl_renderer *gr = get_renderer(surface->compositor);
1523 struct gl_surface_state *gs = get_surface_state(surface);
1524 int cw, ch;
1525 GLuint fbo;
1526 GLuint tex;
1527 GLenum status;
1528 const GLfloat *proj;
1529 int i;
1530
1531 gl_renderer_surface_get_content_size(surface, &cw, &ch);
1532
1533 switch (gs->buffer_type) {
1534 case BUFFER_TYPE_NULL:
1535 return -1;
1536 case BUFFER_TYPE_SOLID:
1537 *(uint32_t *)target = pack_color(format, gs->color);
1538 return 0;
1539 case BUFFER_TYPE_SHM:
1540 gl_renderer_flush_damage(surface);
1541 /* fall through */
1542 case BUFFER_TYPE_EGL:
1543 break;
1544 }
1545
1546 glGenTextures(1, &tex);
1547 glBindTexture(GL_TEXTURE_2D, tex);
1548 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cw, ch,
1549 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1550 glBindTexture(GL_TEXTURE_2D, 0);
1551
1552 glGenFramebuffers(1, &fbo);
1553 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1554 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1555 GL_TEXTURE_2D, tex, 0);
1556
1557 status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
1558 if (status != GL_FRAMEBUFFER_COMPLETE) {
1559 weston_log("%s: fbo error: %#x\n", __func__, status);
1560 glDeleteFramebuffers(1, &fbo);
1561 glDeleteTextures(1, &tex);
1562 return -1;
1563 }
1564
1565 glViewport(0, 0, cw, ch);
1566 glDisable(GL_BLEND);
1567 use_shader(gr, gs->shader);
1568 if (gs->y_inverted)
1569 proj = projmat_normal;
1570 else
1571 proj = projmat_yinvert;
1572
1573 glUniformMatrix4fv(gs->shader->proj_uniform, 1, GL_FALSE, proj);
1574 glUniform1f(gs->shader->alpha_uniform, 1.0f);
1575
1576 for (i = 0; i < gs->num_textures; i++) {
1577 glUniform1i(gs->shader->tex_uniforms[i], i);
1578
1579 glActiveTexture(GL_TEXTURE0 + i);
1580 glBindTexture(gs->target, gs->textures[i]);
1581 glTexParameteri(gs->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1582 glTexParameteri(gs->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1583 }
1584
1585 /* position: */
1586 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
1587 glEnableVertexAttribArray(0);
1588
1589 /* texcoord: */
1590 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, verts);
1591 glEnableVertexAttribArray(1);
1592
1593 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1594
1595 glDisableVertexAttribArray(1);
1596 glDisableVertexAttribArray(0);
1597
1598 glPixelStorei(GL_PACK_ALIGNMENT, bytespp);
1599 glReadPixels(src_x, src_y, width, height, gl_format,
1600 GL_UNSIGNED_BYTE, target);
1601
1602 glDeleteFramebuffers(1, &fbo);
1603 glDeleteTextures(1, &tex);
1604
1605 return 0;
1606}
1607
1608static void
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001609surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr)
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001610{
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001611 int i;
1612
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001613 wl_list_remove(&gs->surface_destroy_listener.link);
1614 wl_list_remove(&gs->renderer_destroy_listener.link);
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001615
1616 gs->surface->renderer_state = NULL;
1617
1618 glDeleteTextures(gs->num_textures, gs->textures);
1619
1620 for (i = 0; i < gs->num_images; i++)
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +03001621 egl_image_unref(gs->images[i]);
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001622
1623 weston_buffer_reference(&gs->buffer_ref, NULL);
1624 pixman_region32_fini(&gs->texture_damage);
1625 free(gs);
1626}
1627
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001628static void
1629surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
1630{
1631 struct gl_surface_state *gs;
1632 struct gl_renderer *gr;
1633
1634 gs = container_of(listener, struct gl_surface_state,
1635 surface_destroy_listener);
1636
1637 gr = get_renderer(gs->surface->compositor);
1638
1639 surface_state_destroy(gs, gr);
1640}
1641
1642static void
1643surface_state_handle_renderer_destroy(struct wl_listener *listener, void *data)
1644{
1645 struct gl_surface_state *gs;
1646 struct gl_renderer *gr;
1647
1648 gr = data;
1649
1650 gs = container_of(listener, struct gl_surface_state,
1651 renderer_destroy_listener);
1652
1653 surface_state_destroy(gs, gr);
1654}
1655
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001656static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001657gl_renderer_create_surface(struct weston_surface *surface)
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001658{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001659 struct gl_surface_state *gs;
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001660 struct gl_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001661
Bryce Harringtonde16d892014-11-20 22:21:57 -08001662 gs = zalloc(sizeof *gs);
1663 if (gs == NULL)
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001664 return -1;
1665
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001666 /* A buffer is never attached to solid color surfaces, yet
1667 * they still go through texcoord computations. Do not divide
1668 * by zero there.
1669 */
1670 gs->pitch = 1;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001671 gs->y_inverted = 1;
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001672
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001673 gs->surface = surface;
1674
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001675 pixman_region32_init(&gs->texture_damage);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001676 surface->renderer_state = gs;
1677
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001678 gs->surface_destroy_listener.notify =
1679 surface_state_handle_surface_destroy;
1680 wl_signal_add(&surface->destroy_signal,
1681 &gs->surface_destroy_listener);
1682
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001683 gs->renderer_destroy_listener.notify =
1684 surface_state_handle_renderer_destroy;
1685 wl_signal_add(&gr->destroy_signal,
1686 &gs->renderer_destroy_listener);
1687
Ander Conselvan de Oliveira895b1fd2013-11-19 15:22:05 +02001688 if (surface->buffer_ref.buffer) {
1689 gl_renderer_attach(surface, surface->buffer_ref.buffer);
1690 gl_renderer_flush_damage(surface);
1691 }
1692
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001693 return 0;
1694}
1695
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001696static const char vertex_shader[] =
1697 "uniform mat4 proj;\n"
1698 "attribute vec2 position;\n"
1699 "attribute vec2 texcoord;\n"
1700 "varying vec2 v_texcoord;\n"
1701 "void main()\n"
1702 "{\n"
1703 " gl_Position = proj * vec4(position, 0.0, 1.0);\n"
1704 " v_texcoord = texcoord;\n"
1705 "}\n";
1706
1707/* Declare common fragment shader uniforms */
1708#define FRAGMENT_CONVERT_YUV \
1709 " y *= alpha;\n" \
1710 " u *= alpha;\n" \
1711 " v *= alpha;\n" \
1712 " gl_FragColor.r = y + 1.59602678 * v;\n" \
1713 " gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n" \
1714 " gl_FragColor.b = y + 2.01723214 * u;\n" \
1715 " gl_FragColor.a = alpha;\n"
1716
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001717static const char fragment_debug[] =
1718 " gl_FragColor = vec4(0.0, 0.3, 0.0, 0.2) + gl_FragColor * 0.8;\n";
1719
1720static const char fragment_brace[] =
1721 "}\n";
1722
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001723static const char texture_fragment_shader_rgba[] =
1724 "precision mediump float;\n"
1725 "varying vec2 v_texcoord;\n"
1726 "uniform sampler2D tex;\n"
1727 "uniform float alpha;\n"
1728 "void main()\n"
1729 "{\n"
1730 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001731 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001732
1733static const char texture_fragment_shader_rgbx[] =
1734 "precision mediump float;\n"
1735 "varying vec2 v_texcoord;\n"
1736 "uniform sampler2D tex;\n"
1737 "uniform float alpha;\n"
1738 "void main()\n"
1739 "{\n"
1740 " gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb\n;"
1741 " gl_FragColor.a = alpha;\n"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001742 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001743
1744static const char texture_fragment_shader_egl_external[] =
1745 "#extension GL_OES_EGL_image_external : require\n"
1746 "precision mediump float;\n"
1747 "varying vec2 v_texcoord;\n"
1748 "uniform samplerExternalOES tex;\n"
1749 "uniform float alpha;\n"
1750 "void main()\n"
1751 "{\n"
1752 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001753 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001754
1755static const char texture_fragment_shader_y_uv[] =
1756 "precision mediump float;\n"
1757 "uniform sampler2D tex;\n"
1758 "uniform sampler2D tex1;\n"
1759 "varying vec2 v_texcoord;\n"
1760 "uniform float alpha;\n"
1761 "void main() {\n"
1762 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1763 " float u = texture2D(tex1, v_texcoord).r - 0.5;\n"
1764 " float v = texture2D(tex1, v_texcoord).g - 0.5;\n"
1765 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001766 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001767
1768static const char texture_fragment_shader_y_u_v[] =
1769 "precision mediump float;\n"
1770 "uniform sampler2D tex;\n"
1771 "uniform sampler2D tex1;\n"
1772 "uniform sampler2D tex2;\n"
1773 "varying vec2 v_texcoord;\n"
1774 "uniform float alpha;\n"
1775 "void main() {\n"
1776 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1777 " float u = texture2D(tex1, v_texcoord).x - 0.5;\n"
1778 " float v = texture2D(tex2, v_texcoord).x - 0.5;\n"
1779 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001780 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001781
1782static const char texture_fragment_shader_y_xuxv[] =
1783 "precision mediump float;\n"
1784 "uniform sampler2D tex;\n"
1785 "uniform sampler2D tex1;\n"
1786 "varying vec2 v_texcoord;\n"
1787 "uniform float alpha;\n"
1788 "void main() {\n"
1789 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1790 " float u = texture2D(tex1, v_texcoord).g - 0.5;\n"
1791 " float v = texture2D(tex1, v_texcoord).a - 0.5;\n"
1792 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001793 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001794
1795static const char solid_fragment_shader[] =
1796 "precision mediump float;\n"
1797 "uniform vec4 color;\n"
1798 "uniform float alpha;\n"
1799 "void main()\n"
1800 "{\n"
1801 " gl_FragColor = alpha * color\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001802 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001803
1804static int
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001805compile_shader(GLenum type, int count, const char **sources)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001806{
1807 GLuint s;
1808 char msg[512];
1809 GLint status;
1810
1811 s = glCreateShader(type);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001812 glShaderSource(s, count, sources, NULL);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001813 glCompileShader(s);
1814 glGetShaderiv(s, GL_COMPILE_STATUS, &status);
1815 if (!status) {
1816 glGetShaderInfoLog(s, sizeof msg, NULL, msg);
1817 weston_log("shader info: %s\n", msg);
1818 return GL_NONE;
1819 }
1820
1821 return s;
1822}
1823
1824static int
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03001825shader_init(struct gl_shader *shader, struct gl_renderer *renderer,
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001826 const char *vertex_source, const char *fragment_source)
1827{
1828 char msg[512];
1829 GLint status;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001830 int count;
1831 const char *sources[3];
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001832
1833 shader->vertex_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001834 compile_shader(GL_VERTEX_SHADER, 1, &vertex_source);
1835
1836 if (renderer->fragment_shader_debug) {
1837 sources[0] = fragment_source;
1838 sources[1] = fragment_debug;
1839 sources[2] = fragment_brace;
1840 count = 3;
1841 } else {
1842 sources[0] = fragment_source;
1843 sources[1] = fragment_brace;
1844 count = 2;
1845 }
1846
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001847 shader->fragment_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001848 compile_shader(GL_FRAGMENT_SHADER, count, sources);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001849
1850 shader->program = glCreateProgram();
1851 glAttachShader(shader->program, shader->vertex_shader);
1852 glAttachShader(shader->program, shader->fragment_shader);
1853 glBindAttribLocation(shader->program, 0, "position");
1854 glBindAttribLocation(shader->program, 1, "texcoord");
1855
1856 glLinkProgram(shader->program);
1857 glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
1858 if (!status) {
1859 glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
1860 weston_log("link info: %s\n", msg);
1861 return -1;
1862 }
1863
1864 shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
1865 shader->tex_uniforms[0] = glGetUniformLocation(shader->program, "tex");
1866 shader->tex_uniforms[1] = glGetUniformLocation(shader->program, "tex1");
1867 shader->tex_uniforms[2] = glGetUniformLocation(shader->program, "tex2");
1868 shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
1869 shader->color_uniform = glGetUniformLocation(shader->program, "color");
1870
1871 return 0;
1872}
1873
1874static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001875shader_release(struct gl_shader *shader)
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001876{
1877 glDeleteShader(shader->vertex_shader);
1878 glDeleteShader(shader->fragment_shader);
1879 glDeleteProgram(shader->program);
1880
1881 shader->vertex_shader = 0;
1882 shader->fragment_shader = 0;
1883 shader->program = 0;
1884}
1885
1886static void
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001887log_extensions(const char *name, const char *extensions)
1888{
1889 const char *p, *end;
1890 int l;
1891 int len;
1892
1893 l = weston_log("%s:", name);
1894 p = extensions;
1895 while (*p) {
1896 end = strchrnul(p, ' ');
1897 len = end - p;
1898 if (l + len > 78)
1899 l = weston_log_continue("\n" STAMP_SPACE "%.*s",
1900 len, p);
1901 else
1902 l += weston_log_continue(" %.*s", len, p);
1903 for (p = end; isspace(*p); p++)
1904 ;
1905 }
1906 weston_log_continue("\n");
1907}
1908
1909static void
1910log_egl_gl_info(EGLDisplay egldpy)
1911{
1912 const char *str;
1913
1914 str = eglQueryString(egldpy, EGL_VERSION);
1915 weston_log("EGL version: %s\n", str ? str : "(null)");
1916
1917 str = eglQueryString(egldpy, EGL_VENDOR);
1918 weston_log("EGL vendor: %s\n", str ? str : "(null)");
1919
1920 str = eglQueryString(egldpy, EGL_CLIENT_APIS);
1921 weston_log("EGL client APIs: %s\n", str ? str : "(null)");
1922
1923 str = eglQueryString(egldpy, EGL_EXTENSIONS);
1924 log_extensions("EGL extensions", str ? str : "(null)");
1925
1926 str = (char *)glGetString(GL_VERSION);
1927 weston_log("GL version: %s\n", str ? str : "(null)");
1928
1929 str = (char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
1930 weston_log("GLSL version: %s\n", str ? str : "(null)");
1931
1932 str = (char *)glGetString(GL_VENDOR);
1933 weston_log("GL vendor: %s\n", str ? str : "(null)");
1934
1935 str = (char *)glGetString(GL_RENDERER);
1936 weston_log("GL renderer: %s\n", str ? str : "(null)");
1937
1938 str = (char *)glGetString(GL_EXTENSIONS);
1939 log_extensions("GL extensions", str ? str : "(null)");
1940}
1941
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001942static void
1943log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
1944{
1945 EGLint r, g, b, a;
1946
1947 weston_log("Chosen EGL config details:\n");
1948
1949 weston_log_continue(STAMP_SPACE "RGBA bits");
1950 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_RED_SIZE, &r) &&
1951 eglGetConfigAttrib(egldpy, eglconfig, EGL_GREEN_SIZE, &g) &&
1952 eglGetConfigAttrib(egldpy, eglconfig, EGL_BLUE_SIZE, &b) &&
1953 eglGetConfigAttrib(egldpy, eglconfig, EGL_ALPHA_SIZE, &a))
1954 weston_log_continue(": %d %d %d %d\n", r, g, b, a);
1955 else
1956 weston_log_continue(" unknown\n");
1957
1958 weston_log_continue(STAMP_SPACE "swap interval range");
1959 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_MIN_SWAP_INTERVAL, &a) &&
1960 eglGetConfigAttrib(egldpy, eglconfig, EGL_MAX_SWAP_INTERVAL, &b))
1961 weston_log_continue(": %d - %d\n", a, b);
1962 else
1963 weston_log_continue(" unknown\n");
1964}
1965
Neil Roberts77c1a5b2014-03-07 18:05:50 +00001966static int
Derek Foremane76f1852015-05-15 12:12:39 -05001967match_config_to_visual(EGLDisplay egl_display,
1968 EGLint visual_id,
1969 EGLConfig *configs,
1970 int count)
1971{
1972 int i;
1973
1974 for (i = 0; i < count; ++i) {
1975 EGLint id;
1976
1977 if (!eglGetConfigAttrib(egl_display,
1978 configs[i], EGL_NATIVE_VISUAL_ID,
1979 &id))
1980 continue;
1981
1982 if (id == visual_id)
1983 return i;
1984 }
1985
Derek Foremane76f1852015-05-15 12:12:39 -05001986 return -1;
1987}
1988
1989static int
Neil Roberts77c1a5b2014-03-07 18:05:50 +00001990egl_choose_config(struct gl_renderer *gr, const EGLint *attribs,
Derek Foremane76f1852015-05-15 12:12:39 -05001991 const EGLint *visual_id, const int n_ids,
Neil Roberts77c1a5b2014-03-07 18:05:50 +00001992 EGLConfig *config_out)
1993{
1994 EGLint count = 0;
1995 EGLint matched = 0;
1996 EGLConfig *configs;
Derek Foremane76f1852015-05-15 12:12:39 -05001997 int i, config_index = -1;
Neil Roberts77c1a5b2014-03-07 18:05:50 +00001998
Derek Foremana7e19912015-05-20 14:57:58 -05001999 if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1) {
2000 weston_log("No EGL configs to choose from.\n");
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002001 return -1;
Derek Foremana7e19912015-05-20 14:57:58 -05002002 }
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002003 configs = calloc(count, sizeof *configs);
2004 if (!configs)
2005 return -1;
2006
2007 if (!eglChooseConfig(gr->egl_display, attribs, configs,
Derek Foremana7e19912015-05-20 14:57:58 -05002008 count, &matched) || !matched) {
2009 weston_log("No EGL configs with appropriate attributes.\n");
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002010 goto out;
Derek Foremana7e19912015-05-20 14:57:58 -05002011 }
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002012
Derek Foremane76f1852015-05-15 12:12:39 -05002013 if (!visual_id)
2014 config_index = 0;
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002015
Derek Foremane76f1852015-05-15 12:12:39 -05002016 for (i = 0; config_index == -1 && i < n_ids; i++)
2017 config_index = match_config_to_visual(gr->egl_display,
2018 visual_id[i],
2019 configs,
2020 matched);
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002021
Derek Foremane76f1852015-05-15 12:12:39 -05002022 if (config_index != -1)
2023 *config_out = configs[config_index];
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002024
2025out:
2026 free(configs);
Derek Foremane76f1852015-05-15 12:12:39 -05002027 if (config_index == -1)
2028 return -1;
2029
Derek Foremana7e19912015-05-20 14:57:58 -05002030 if (i > 1)
2031 weston_log("Unable to use first choice EGL config with id"
2032 " 0x%x, succeeded with alternate id 0x%x.\n",
2033 visual_id[0], visual_id[i - 1]);
Derek Foremane76f1852015-05-15 12:12:39 -05002034 return 0;
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002035}
2036
John Kåre Alsaker44154502012-11-13 19:10:20 +01002037static void
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05002038gl_renderer_output_set_border(struct weston_output *output,
2039 enum gl_renderer_border_side side,
2040 int32_t width, int32_t height,
2041 int32_t tex_width, unsigned char *data)
2042{
2043 struct gl_output_state *go = get_output_state(output);
2044
Jason Ekstrande5512d42014-02-04 21:36:38 -06002045 if (go->borders[side].width != width ||
2046 go->borders[side].height != height)
2047 /* In this case, we have to blow everything and do a full
2048 * repaint. */
2049 go->border_status |= BORDER_SIZE_CHANGED | BORDER_ALL_DIRTY;
2050
2051 if (data == NULL) {
2052 width = 0;
2053 height = 0;
2054 }
2055
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05002056 go->borders[side].width = width;
2057 go->borders[side].height = height;
2058 go->borders[side].tex_width = tex_width;
2059 go->borders[side].data = data;
Jason Ekstrande5512d42014-02-04 21:36:38 -06002060 go->border_status |= 1 << side;
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05002061}
2062
John Kåre Alsaker94659272012-11-13 19:10:18 +01002063static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002064gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01002065
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002066static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002067gl_renderer_output_create(struct weston_output *output,
Jonny Lamb671148f2015-03-20 15:26:52 +01002068 EGLNativeWindowType window_for_legacy,
2069 void *window_for_platform,
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002070 const EGLint *attribs,
Derek Foremane76f1852015-05-15 12:12:39 -05002071 const EGLint *visual_id,
2072 int n_ids)
John Kåre Alsaker94659272012-11-13 19:10:18 +01002073{
2074 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002075 struct gl_renderer *gr = get_renderer(ec);
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002076 struct gl_output_state *go;
2077 EGLConfig egl_config;
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02002078 int i;
John Kåre Alsaker94659272012-11-13 19:10:18 +01002079
Derek Foremane76f1852015-05-15 12:12:39 -05002080 if (egl_choose_config(gr, attribs, visual_id,
2081 n_ids, &egl_config) == -1) {
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002082 weston_log("failed to choose EGL config for output\n");
2083 return -1;
2084 }
2085
2086 if (egl_config != gr->egl_config &&
2087 !gr->has_configless_context) {
2088 weston_log("attempted to use a different EGL config for an "
2089 "output but EGL_MESA_configless_context is not "
2090 "supported\n");
2091 return -1;
2092 }
2093
Bryce Harringtonde16d892014-11-20 22:21:57 -08002094 go = zalloc(sizeof *go);
2095 if (go == NULL)
John Kåre Alsaker94659272012-11-13 19:10:18 +01002096 return -1;
2097
Jonny Lamb671148f2015-03-20 15:26:52 +01002098 if (gr->create_platform_window) {
2099 go->egl_surface =
2100 gr->create_platform_window(gr->egl_display,
2101 egl_config,
2102 window_for_platform,
2103 NULL);
Jonny Lambf1ec5062015-03-24 13:12:05 +01002104 } else {
Jonny Lamb671148f2015-03-20 15:26:52 +01002105 go->egl_surface =
2106 eglCreateWindowSurface(gr->egl_display,
2107 egl_config,
2108 window_for_legacy, NULL);
Jonny Lambf1ec5062015-03-24 13:12:05 +01002109 }
John Kåre Alsaker94659272012-11-13 19:10:18 +01002110
2111 if (go->egl_surface == EGL_NO_SURFACE) {
2112 weston_log("failed to create egl surface\n");
2113 free(go);
2114 return -1;
2115 }
2116
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002117 if (gr->egl_context == NULL)
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002118 if (gl_renderer_setup(ec, go->egl_surface) < 0) {
John Kåre Alsaker94659272012-11-13 19:10:18 +01002119 free(go);
2120 return -1;
2121 }
2122
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02002123 for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02002124 pixman_region32_init(&go->buffer_damage[i]);
2125
John Kåre Alsaker94659272012-11-13 19:10:18 +01002126 output->renderer_state = go;
2127
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002128 log_egl_config_info(gr->egl_display, egl_config);
2129
John Kåre Alsaker94659272012-11-13 19:10:18 +01002130 return 0;
2131}
2132
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002133static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002134gl_renderer_output_destroy(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01002135{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002136 struct gl_renderer *gr = get_renderer(output->compositor);
2137 struct gl_output_state *go = get_output_state(output);
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02002138 int i;
2139
2140 for (i = 0; i < 2; i++)
2141 pixman_region32_fini(&go->buffer_damage[i]);
John Kåre Alsaker94659272012-11-13 19:10:18 +01002142
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002143 eglDestroySurface(gr->egl_display, go->egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01002144
2145 free(go);
2146}
2147
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002148static EGLSurface
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002149gl_renderer_output_surface(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01002150{
2151 return get_output_state(output)->egl_surface;
2152}
2153
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03002154static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002155gl_renderer_destroy(struct weston_compositor *ec)
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04002156{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002157 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002158
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03002159 wl_signal_emit(&gr->destroy_signal, gr);
2160
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002161 if (gr->has_bind_display)
2162 gr->unbind_display(gr->egl_display, ec->wl_display);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002163
2164 /* Work around crash in egl_dri2.c's dri2_make_current() - when does this apply? */
2165 eglMakeCurrent(gr->egl_display,
2166 EGL_NO_SURFACE, EGL_NO_SURFACE,
2167 EGL_NO_CONTEXT);
2168
2169 eglTerminate(gr->egl_display);
2170 eglReleaseThread();
Scott Moreau976a0502013-03-07 10:15:17 -07002171
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -04002172 wl_array_release(&gr->vertices);
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -04002173 wl_array_release(&gr->vtxcnt);
2174
Mariusz Ceiercbb91582014-02-08 20:11:24 +01002175 if (gr->fragment_binding)
2176 weston_binding_destroy(gr->fragment_binding);
2177 if (gr->fan_binding)
2178 weston_binding_destroy(gr->fan_binding);
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +03002179
Scott Moreau976a0502013-03-07 10:15:17 -07002180 free(gr);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002181}
2182
Pekka Paalanen8b69d032015-04-08 17:02:22 +03002183static void
2184renderer_setup_egl_client_extensions(struct gl_renderer *gr)
2185{
2186 const char *extensions;
2187
2188 extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
2189 if (!extensions) {
2190 weston_log("Retrieving EGL client extension string failed.\n");
2191 return;
2192 }
2193
2194 if (strstr(extensions, "EGL_EXT_platform_base"))
2195 gr->create_platform_window =
2196 (void *) eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT");
2197 else
2198 weston_log("warning: EGL_EXT_platform_base not supported.\n");
2199}
2200
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002201static int
Neil Robertsb7f85332014-03-07 18:05:49 +00002202gl_renderer_setup_egl_extensions(struct weston_compositor *ec)
2203{
2204 struct gl_renderer *gr = get_renderer(ec);
2205 const char *extensions;
2206 EGLBoolean ret;
2207
2208 gr->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
2209 gr->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
2210 gr->bind_display =
2211 (void *) eglGetProcAddress("eglBindWaylandDisplayWL");
2212 gr->unbind_display =
2213 (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
2214 gr->query_buffer =
2215 (void *) eglGetProcAddress("eglQueryWaylandBufferWL");
2216
2217 extensions =
2218 (const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
2219 if (!extensions) {
2220 weston_log("Retrieving EGL extension string failed.\n");
2221 return -1;
2222 }
2223
2224 if (strstr(extensions, "EGL_WL_bind_wayland_display"))
2225 gr->has_bind_display = 1;
2226 if (gr->has_bind_display) {
2227 ret = gr->bind_display(gr->egl_display, ec->wl_display);
2228 if (!ret)
2229 gr->has_bind_display = 0;
2230 }
2231
2232 if (strstr(extensions, "EGL_EXT_buffer_age"))
2233 gr->has_egl_buffer_age = 1;
2234 else
2235 weston_log("warning: EGL_EXT_buffer_age not supported. "
2236 "Performance could be affected.\n");
2237
2238#ifdef EGL_EXT_swap_buffers_with_damage
2239 if (strstr(extensions, "EGL_EXT_swap_buffers_with_damage"))
2240 gr->swap_buffers_with_damage =
2241 (void *) eglGetProcAddress("eglSwapBuffersWithDamageEXT");
2242 else
2243 weston_log("warning: EGL_EXT_swap_buffers_with_damage not "
2244 "supported. Performance could be affected.\n");
2245#endif
2246
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002247#ifdef EGL_MESA_configless_context
2248 if (strstr(extensions, "EGL_MESA_configless_context"))
2249 gr->has_configless_context = 1;
2250#endif
2251
Pekka Paalanen8b69d032015-04-08 17:02:22 +03002252 renderer_setup_egl_client_extensions(gr);
2253
Neil Robertsb7f85332014-03-07 18:05:49 +00002254 return 0;
2255}
2256
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002257static const EGLint gl_renderer_opaque_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002258 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
2259 EGL_RED_SIZE, 1,
2260 EGL_GREEN_SIZE, 1,
2261 EGL_BLUE_SIZE, 1,
2262 EGL_ALPHA_SIZE, 0,
2263 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
2264 EGL_NONE
2265};
2266
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002267static const EGLint gl_renderer_alpha_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002268 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
2269 EGL_RED_SIZE, 1,
2270 EGL_GREEN_SIZE, 1,
2271 EGL_BLUE_SIZE, 1,
2272 EGL_ALPHA_SIZE, 1,
2273 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
2274 EGL_NONE
2275};
2276
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002277/** Checks whether a platform EGL client extension is supported
2278 *
2279 * \param ec The weston compositor
2280 * \param extension_suffix The EGL client extension suffix
2281 * \return 1 if supported, 0 if using fallbacks, -1 unsupported
2282 *
2283 * This function checks whether a specific platform_* extension is supported
2284 * by EGL.
2285 *
2286 * The extension suffix should be the suffix of the platform extension (that
2287 * specifies a <platform> argument as defined in EGL_EXT_platform_base). For
2288 * example, passing "foo" will check whether either "EGL_KHR_platform_foo",
2289 * "EGL_EXT_platform_foo", or "EGL_MESA_platform_foo" is supported.
2290 *
2291 * The return value is 1:
2292 * - if the supplied EGL client extension is supported.
2293 * The return value is 0:
2294 * - if the platform_base client extension isn't supported so will
2295 * fallback to eglGetDisplay and friends.
2296 * The return value is -1:
2297 * - if the supplied EGL client extension is not supported.
2298 */
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002299static int
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002300gl_renderer_supports(struct weston_compositor *ec,
2301 const char *extension_suffix)
2302{
2303 static const char *extensions = NULL;
2304 char s[64];
2305
2306 if (!extensions) {
2307 extensions = (const char *) eglQueryString(
2308 EGL_NO_DISPLAY, EGL_EXTENSIONS);
2309
2310 if (!extensions)
2311 return 0;
2312
2313 log_extensions("EGL client extensions",
2314 extensions);
2315 }
2316
Pekka Paalanenf2824542015-04-08 17:02:21 +03002317 if (!strstr(extensions, "EGL_EXT_platform_base"))
2318 return 0;
2319
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002320 snprintf(s, sizeof s, "EGL_KHR_platform_%s", extension_suffix);
2321 if (strstr(extensions, s))
2322 return 1;
2323
2324 snprintf(s, sizeof s, "EGL_EXT_platform_%s", extension_suffix);
2325 if (strstr(extensions, s))
2326 return 1;
2327
2328 snprintf(s, sizeof s, "EGL_MESA_platform_%s", extension_suffix);
2329 if (strstr(extensions, s))
2330 return 1;
2331
Pekka Paalanenf2824542015-04-08 17:02:21 +03002332 /* at this point we definitely have some platform extensions but
2333 * haven't found the supplied platform, so chances are it's
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002334 * not supported. */
2335
2336 return -1;
2337}
2338
Jonny Lamb74eed312015-03-24 13:12:04 +01002339static const char *
2340platform_to_extension(EGLenum platform)
2341{
2342 switch (platform) {
2343 case EGL_PLATFORM_GBM_KHR:
2344 return "gbm";
2345 case EGL_PLATFORM_WAYLAND_KHR:
2346 return "wayland";
2347 case EGL_PLATFORM_X11_KHR:
2348 return "x11";
2349 default:
2350 assert(0 && "bad EGL platform enum");
2351 }
2352}
2353
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002354static int
2355gl_renderer_create(struct weston_compositor *ec, EGLenum platform,
2356 void *native_window, const EGLint *attribs,
Derek Foremane76f1852015-05-15 12:12:39 -05002357 const EGLint *visual_id, int n_ids)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002358{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002359 struct gl_renderer *gr;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002360 EGLint major, minor;
Jonny Lamb74eed312015-03-24 13:12:04 +01002361 int supports = 0;
2362
2363 if (platform) {
2364 supports = gl_renderer_supports(
2365 ec, platform_to_extension(platform));
2366 if (supports < 0)
2367 return -1;
2368 }
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002369
Bryce Harringtonde16d892014-11-20 22:21:57 -08002370 gr = zalloc(sizeof *gr);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002371 if (gr == NULL)
2372 return -1;
2373
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002374 gr->base.read_pixels = gl_renderer_read_pixels;
2375 gr->base.repaint_output = gl_renderer_repaint_output;
2376 gr->base.flush_damage = gl_renderer_flush_damage;
2377 gr->base.attach = gl_renderer_attach;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002378 gr->base.surface_set_color = gl_renderer_surface_set_color;
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03002379 gr->base.destroy = gl_renderer_destroy;
Pekka Paalaneneb35cbe2015-02-09 13:37:27 +02002380 gr->base.surface_get_content_size =
2381 gl_renderer_surface_get_content_size;
2382 gr->base.surface_copy_content = gl_renderer_surface_copy_content;
Jonny Lamb74eed312015-03-24 13:12:04 +01002383 gr->egl_display = NULL;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002384
Jonny Lambf1ec5062015-03-24 13:12:05 +01002385 /* extension_suffix is supported */
Jonny Lamb74eed312015-03-24 13:12:04 +01002386 if (supports) {
2387 if (!get_platform_display) {
2388 get_platform_display = (void *) eglGetProcAddress(
2389 "eglGetPlatformDisplayEXT");
2390 }
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002391
Jonny Lamb74eed312015-03-24 13:12:04 +01002392 /* also wrap this in the supports check because
2393 * eglGetProcAddress can return non-NULL and still not
2394 * support the feature at runtime, so ensure the
2395 * appropriate extension checks have been done. */
2396 if (get_platform_display && platform) {
2397 gr->egl_display = get_platform_display(platform,
2398 native_window,
2399 NULL);
2400 }
2401 }
Jonny Lamb74eed312015-03-24 13:12:04 +01002402
2403 if (!gr->egl_display) {
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002404 weston_log("warning: either no EGL_EXT_platform_base "
2405 "support or specific platform support; "
2406 "falling back to eglGetDisplay.\n");
2407 gr->egl_display = eglGetDisplay(native_window);
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002408 }
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002409
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002410 if (gr->egl_display == EGL_NO_DISPLAY) {
2411 weston_log("failed to create display\n");
Derek Foreman066ca0c2015-06-11 12:14:45 -05002412 goto fail;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002413 }
2414
2415 if (!eglInitialize(gr->egl_display, &major, &minor)) {
2416 weston_log("failed to initialize display\n");
Derek Foreman066ca0c2015-06-11 12:14:45 -05002417 goto fail_with_error;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002418 }
2419
Derek Foremane76f1852015-05-15 12:12:39 -05002420 if (egl_choose_config(gr, attribs, visual_id,
2421 n_ids, &gr->egl_config) < 0) {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002422 weston_log("failed to choose EGL config\n");
Derek Foreman066ca0c2015-06-11 12:14:45 -05002423 goto fail;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002424 }
2425
2426 ec->renderer = &gr->base;
Pekka Paalanen7bb65102013-05-22 18:03:04 +03002427 ec->capabilities |= WESTON_CAP_ROTATION_ANY;
Pekka Paalanen4fc5dd02013-05-22 18:03:05 +03002428 ec->capabilities |= WESTON_CAP_CAPTURE_YFLIP;
Pekka Paalanenfa79b1d2015-02-18 09:48:59 +02002429 ec->capabilities |= WESTON_CAP_VIEW_CLIP_MASK;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002430
Neil Robertsb7f85332014-03-07 18:05:49 +00002431 if (gl_renderer_setup_egl_extensions(ec) < 0)
Derek Foreman066ca0c2015-06-11 12:14:45 -05002432 goto fail_with_error;
Neil Robertsb7f85332014-03-07 18:05:49 +00002433
Tomeu Vizoso12072b62013-08-06 20:05:55 +02002434 wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565);
2435
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03002436 wl_signal_init(&gr->destroy_signal);
2437
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002438 return 0;
2439
Derek Foreman066ca0c2015-06-11 12:14:45 -05002440fail_with_error:
Pekka Paalanen326529f2012-11-27 12:25:25 +02002441 gl_renderer_print_egl_error_state();
Derek Foreman066ca0c2015-06-11 12:14:45 -05002442fail:
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002443 free(gr);
2444 return -1;
2445}
2446
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002447static EGLDisplay
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002448gl_renderer_display(struct weston_compositor *ec)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002449{
2450 return get_renderer(ec)->egl_display;
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04002451}
2452
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002453static int
2454compile_shaders(struct weston_compositor *ec)
2455{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002456 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker40684142012-11-13 19:10:25 +01002457
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03002458 gr->texture_shader_rgba.vertex_source = vertex_shader;
2459 gr->texture_shader_rgba.fragment_source = texture_fragment_shader_rgba;
2460
2461 gr->texture_shader_rgbx.vertex_source = vertex_shader;
2462 gr->texture_shader_rgbx.fragment_source = texture_fragment_shader_rgbx;
2463
2464 gr->texture_shader_egl_external.vertex_source = vertex_shader;
2465 gr->texture_shader_egl_external.fragment_source =
2466 texture_fragment_shader_egl_external;
2467
2468 gr->texture_shader_y_uv.vertex_source = vertex_shader;
2469 gr->texture_shader_y_uv.fragment_source = texture_fragment_shader_y_uv;
2470
2471 gr->texture_shader_y_u_v.vertex_source = vertex_shader;
2472 gr->texture_shader_y_u_v.fragment_source =
2473 texture_fragment_shader_y_u_v;
2474
Ander Conselvan de Oliveira41a50ea2013-11-27 17:43:51 +02002475 gr->texture_shader_y_xuxv.vertex_source = vertex_shader;
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03002476 gr->texture_shader_y_xuxv.fragment_source =
2477 texture_fragment_shader_y_xuxv;
2478
2479 gr->solid_shader.vertex_source = vertex_shader;
2480 gr->solid_shader.fragment_source = solid_fragment_shader;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002481
2482 return 0;
2483}
2484
2485static void
Derek Foreman8ae2db52015-07-15 13:00:36 -05002486fragment_debug_binding(struct weston_keyboard *keyboard, uint32_t time,
2487 uint32_t key, void *data)
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002488{
2489 struct weston_compositor *ec = data;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002490 struct gl_renderer *gr = get_renderer(ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002491 struct weston_output *output;
2492
John Kåre Alsaker40684142012-11-13 19:10:25 +01002493 gr->fragment_shader_debug ^= 1;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002494
John Kåre Alsaker40684142012-11-13 19:10:25 +01002495 shader_release(&gr->texture_shader_rgba);
2496 shader_release(&gr->texture_shader_rgbx);
2497 shader_release(&gr->texture_shader_egl_external);
2498 shader_release(&gr->texture_shader_y_uv);
2499 shader_release(&gr->texture_shader_y_u_v);
2500 shader_release(&gr->texture_shader_y_xuxv);
2501 shader_release(&gr->solid_shader);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002502
Ander Conselvan de Oliveira03fb4ef2012-12-03 17:08:11 +02002503 /* Force use_shader() to call glUseProgram(), since we need to use
2504 * the recompiled version of the shader. */
2505 gr->current_shader = NULL;
2506
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002507 wl_list_for_each(output, &ec->output_list, link)
2508 weston_output_damage(output);
2509}
2510
Kristian Høgsberg8799d412013-05-07 10:50:09 -04002511static void
Derek Foreman8ae2db52015-07-15 13:00:36 -05002512fan_debug_repaint_binding(struct weston_keyboard *keyboard, uint32_t time,
2513 uint32_t key, void *data)
Kristian Høgsberg8799d412013-05-07 10:50:09 -04002514{
2515 struct weston_compositor *compositor = data;
2516 struct gl_renderer *gr = get_renderer(compositor);
2517
2518 gr->fan_debug = !gr->fan_debug;
2519 weston_compositor_damage_all(compositor);
2520}
2521
John Kåre Alsaker94659272012-11-13 19:10:18 +01002522static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002523gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002524{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002525 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002526 const char *extensions;
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002527 EGLConfig context_config;
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04002528 EGLBoolean ret;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002529
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04002530 static const EGLint context_attribs[] = {
2531 EGL_CONTEXT_CLIENT_VERSION, 2,
2532 EGL_NONE
2533 };
2534
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04002535 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
2536 weston_log("failed to bind EGL_OPENGL_ES_API\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02002537 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04002538 return -1;
2539 }
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03002540
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002541 context_config = gr->egl_config;
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03002542
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002543#ifdef EGL_MESA_configless_context
2544 if (gr->has_configless_context)
2545 context_config = EGL_NO_CONFIG_MESA;
2546#endif
2547
2548 gr->egl_context = eglCreateContext(gr->egl_display, context_config,
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04002549 EGL_NO_CONTEXT, context_attribs);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002550 if (gr->egl_context == NULL) {
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04002551 weston_log("failed to create context\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02002552 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04002553 return -1;
2554 }
2555
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002556 ret = eglMakeCurrent(gr->egl_display, egl_surface,
2557 egl_surface, gr->egl_context);
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04002558 if (ret == EGL_FALSE) {
2559 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02002560 gl_renderer_print_egl_error_state();
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04002561 return -1;
2562 }
2563
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002564 log_egl_gl_info(gr->egl_display);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002565
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002566 gr->image_target_texture_2d =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002567 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002568
2569 extensions = (const char *) glGetString(GL_EXTENSIONS);
2570 if (!extensions) {
2571 weston_log("Retrieving GL extension string failed.\n");
2572 return -1;
2573 }
2574
2575 if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
2576 weston_log("GL_EXT_texture_format_BGRA8888 not available\n");
2577 return -1;
2578 }
2579
2580 if (strstr(extensions, "GL_EXT_read_format_bgra"))
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01002581 ec->read_format = PIXMAN_a8r8g8b8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002582 else
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01002583 ec->read_format = PIXMAN_a8b8g8r8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002584
Kristian Høgsberg1c4f1632013-08-07 12:11:27 -07002585#ifdef GL_EXT_unpack_subimage
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002586 if (strstr(extensions, "GL_EXT_unpack_subimage"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002587 gr->has_unpack_subimage = 1;
Kristian Høgsberg1c4f1632013-08-07 12:11:27 -07002588#endif
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002589
2590 if (strstr(extensions, "GL_OES_EGL_image_external"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002591 gr->has_egl_image_external = 1;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002592
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002593 glActiveTexture(GL_TEXTURE0);
2594
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002595 if (compile_shaders(ec))
2596 return -1;
2597
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +03002598 gr->fragment_binding =
2599 weston_compositor_add_debug_binding(ec, KEY_S,
2600 fragment_debug_binding,
2601 ec);
2602 gr->fan_binding =
2603 weston_compositor_add_debug_binding(ec, KEY_F,
2604 fan_debug_repaint_binding,
2605 ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002606
Pekka Paalanen035a0322012-10-24 09:43:06 +03002607 weston_log("GL ES 2 renderer features:\n");
2608 weston_log_continue(STAMP_SPACE "read-back format: %s\n",
Pekka Paalanenfe4eacf2013-01-10 16:50:42 +02002609 ec->read_format == PIXMAN_a8r8g8b8 ? "BGRA" : "RGBA");
Pekka Paalanen035a0322012-10-24 09:43:06 +03002610 weston_log_continue(STAMP_SPACE "wl_shm sub-image to texture: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002611 gr->has_unpack_subimage ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03002612 weston_log_continue(STAMP_SPACE "EGL Wayland extension: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002613 gr->has_bind_display ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03002614
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002615
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002616 return 0;
2617}
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002618
2619WL_EXPORT struct gl_renderer_interface gl_renderer_interface = {
2620 .opaque_attribs = gl_renderer_opaque_attribs,
2621 .alpha_attribs = gl_renderer_alpha_attribs,
2622
2623 .create = gl_renderer_create,
2624 .display = gl_renderer_display,
2625 .output_create = gl_renderer_output_create,
2626 .output_destroy = gl_renderer_output_destroy,
2627 .output_surface = gl_renderer_output_surface,
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05002628 .output_set_border = gl_renderer_output_set_border,
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002629 .print_egl_error_state = gl_renderer_print_egl_error_state
2630};