blob: ed44c6d495a1f900e89e817aeee6d13633c10ae8 [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>
Jussi Kukkonen649bbce2016-07-19 14:16:27 +030033#include <stdint.h>
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -040034#include <stdlib.h>
Kristian Høgsberg25894fc2012-09-05 22:06:26 -040035#include <string.h>
36#include <ctype.h>
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +030037#include <float.h>
38#include <assert.h>
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +020039#include <linux/input.h>
Pekka Paalanena3525802014-06-12 16:49:29 +030040#include <drm_fourcc.h>
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -040041
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010042#include "gl-renderer.h"
Sam Spilsbury619859c2013-09-13 10:01:21 +080043#include "vertex-clipping.h"
Pekka Paalanena3525802014-06-12 16:49:29 +030044#include "linux-dmabuf.h"
Jonas Ådahl57e48f02015-11-17 16:00:28 +080045#include "linux-dmabuf-unstable-v1-server-protocol.h"
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010046
Jon Cruz35b2eaa2015-06-15 15:37:08 -070047#include "shared/helpers.h"
Emil Velikovf0c3a1c2016-07-04 15:34:18 +010048#include "shared/platform.h"
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010049#include "weston-egl-ext.h"
Kristian Høgsbergd7c17262012-09-05 21:54:15 -040050
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010051struct gl_shader {
John Kåre Alsaker40684142012-11-13 19:10:25 +010052 GLuint program;
53 GLuint vertex_shader, fragment_shader;
54 GLint proj_uniform;
55 GLint tex_uniforms[3];
56 GLint alpha_uniform;
57 GLint color_uniform;
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +030058 const char *vertex_source, *fragment_source;
John Kåre Alsaker40684142012-11-13 19:10:25 +010059};
60
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +020061#define BUFFER_DAMAGE_COUNT 2
62
Jason Ekstrande5512d42014-02-04 21:36:38 -060063enum gl_border_status {
64 BORDER_STATUS_CLEAN = 0,
65 BORDER_TOP_DIRTY = 1 << GL_RENDERER_BORDER_TOP,
66 BORDER_LEFT_DIRTY = 1 << GL_RENDERER_BORDER_LEFT,
67 BORDER_RIGHT_DIRTY = 1 << GL_RENDERER_BORDER_RIGHT,
68 BORDER_BOTTOM_DIRTY = 1 << GL_RENDERER_BORDER_BOTTOM,
69 BORDER_ALL_DIRTY = 0xf,
70 BORDER_SIZE_CHANGED = 0x10
71};
72
Jason Ekstrand0b61bf42013-10-27 22:24:54 -050073struct gl_border_image {
74 GLuint tex;
75 int32_t width, height;
76 int32_t tex_width;
Jason Ekstrand0b61bf42013-10-27 22:24:54 -050077 void *data;
78};
79
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010080struct gl_output_state {
John Kåre Alsaker94659272012-11-13 19:10:18 +010081 EGLSurface egl_surface;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +020082 pixman_region32_t buffer_damage[BUFFER_DAMAGE_COUNT];
Derek Foreman4c582662014-10-09 18:39:44 -050083 int buffer_damage_index;
Jason Ekstrande5512d42014-02-04 21:36:38 -060084 enum gl_border_status border_damage[BUFFER_DAMAGE_COUNT];
Jason Ekstrand0b61bf42013-10-27 22:24:54 -050085 struct gl_border_image borders[4];
Jason Ekstrande5512d42014-02-04 21:36:38 -060086 enum gl_border_status border_status;
Jason Ekstrandfb23df72014-10-16 10:55:21 -050087
88 struct weston_matrix output_matrix;
John Kåre Alsaker94659272012-11-13 19:10:18 +010089};
90
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +030091enum buffer_type {
92 BUFFER_TYPE_NULL,
Pekka Paalanenaeb917e2015-02-09 13:56:56 +020093 BUFFER_TYPE_SOLID, /* internal solid color surfaces without a buffer */
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +030094 BUFFER_TYPE_SHM,
95 BUFFER_TYPE_EGL
96};
97
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +030098struct gl_renderer;
99
100struct egl_image {
101 struct gl_renderer *renderer;
102 EGLImageKHR image;
103 int refcount;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +0000104};
Pekka Paalanena3525802014-06-12 16:49:29 +0300105
Emmanuel Gil Peyrotbc35fda2016-01-11 19:04:35 +0000106enum import_type {
107 IMPORT_TYPE_INVALID,
108 IMPORT_TYPE_DIRECT,
109 IMPORT_TYPE_GL_CONVERSION
110};
111
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +0000112struct dmabuf_image {
Pekka Paalanena3525802014-06-12 16:49:29 +0300113 struct linux_dmabuf_buffer *dmabuf;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +0000114 int num_images;
115 struct egl_image *images[3];
Pekka Paalanena3525802014-06-12 16:49:29 +0300116 struct wl_list link;
Emmanuel Gil Peyrotbc35fda2016-01-11 19:04:35 +0000117
118 enum import_type import_type;
119 GLenum target;
120 struct gl_shader *shader;
121};
122
123struct yuv_plane_descriptor {
124 int width_divisor;
125 int height_divisor;
126 uint32_t format;
127 int plane_index;
128};
129
130struct yuv_format_descriptor {
131 uint32_t format;
132 int input_planes;
133 int output_planes;
134 int texture_type;
135 struct yuv_plane_descriptor plane[4];
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +0300136};
137
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100138struct gl_surface_state {
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100139 GLfloat color[4];
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100140 struct gl_shader *shader;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100141
142 GLuint textures[3];
143 int num_textures;
Derek Foreman4c11fe72015-11-18 16:32:27 -0600144 bool needs_full_upload;
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200145 pixman_region32_t texture_damage;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100146
Neil Roberts4d085e72014-04-07 15:01:01 +0100147 /* These are only used by SHM surfaces to detect when we need
148 * to do a full upload to specify a new internal texture
149 * format */
150 GLenum gl_format;
151 GLenum gl_pixel_type;
152
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +0300153 struct egl_image* images[3];
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100154 GLenum target;
155 int num_images;
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200156
157 struct weston_buffer_reference buffer_ref;
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +0300158 enum buffer_type buffer_type;
Pekka Paalanen68033ac2012-12-04 15:58:15 +0200159 int pitch; /* in pixels */
Alexander Larsson4ea95522013-05-22 14:41:37 +0200160 int height; /* in pixels */
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +0400161 int y_inverted;
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300162
163 struct weston_surface *surface;
164
165 struct wl_listener surface_destroy_listener;
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +0300166 struct wl_listener renderer_destroy_listener;
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100167};
168
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100169struct gl_renderer {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100170 struct weston_renderer base;
171 int fragment_shader_debug;
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400172 int fan_debug;
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +0300173 struct weston_binding *fragment_binding;
174 struct weston_binding *fan_binding;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100175
176 EGLDisplay egl_display;
177 EGLContext egl_context;
178 EGLConfig egl_config;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100179
Armin Krezović28d240f2016-06-23 11:59:35 +0200180 EGLSurface dummy_surface;
181
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400182 struct wl_array vertices;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400183 struct wl_array vtxcnt;
184
John Kåre Alsaker320711d2012-11-13 19:10:27 +0100185 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
186 PFNEGLCREATEIMAGEKHRPROC create_image;
187 PFNEGLDESTROYIMAGEKHRPROC destroy_image;
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -0600188 PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage;
Jonny Lamb671148f2015-03-20 15:26:52 +0100189 PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC create_platform_window;
Jonny Lamb671148f2015-03-20 15:26:52 +0100190
John Kåre Alsaker320711d2012-11-13 19:10:27 +0100191 int has_unpack_subimage;
192
193 PFNEGLBINDWAYLANDDISPLAYWL bind_display;
194 PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
195 PFNEGLQUERYWAYLANDBUFFERWL query_buffer;
196 int has_bind_display;
197
198 int has_egl_image_external;
199
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200200 int has_egl_buffer_age;
201
Neil Roberts77c1a5b2014-03-07 18:05:50 +0000202 int has_configless_context;
203
Armin Krezović28d240f2016-06-23 11:59:35 +0200204 int has_surfaceless_context;
205
Pekka Paalanena3525802014-06-12 16:49:29 +0300206 int has_dmabuf_import;
207 struct wl_list dmabuf_images;
208
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100209 struct gl_shader texture_shader_rgba;
210 struct gl_shader texture_shader_rgbx;
211 struct gl_shader texture_shader_egl_external;
212 struct gl_shader texture_shader_y_uv;
213 struct gl_shader texture_shader_y_u_v;
214 struct gl_shader texture_shader_y_xuxv;
215 struct gl_shader invert_color_shader;
216 struct gl_shader solid_shader;
217 struct gl_shader *current_shader;
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +0300218
219 struct wl_signal destroy_signal;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100220};
John Kåre Alsaker94659272012-11-13 19:10:18 +0100221
Jonny Lamb70eba3f2015-03-20 15:26:50 +0100222static PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display = NULL;
Jonny Lamb70eba3f2015-03-20 15:26:50 +0100223
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +0000224static inline const char *
225dump_format(uint32_t format, char out[4])
226{
227#if BYTE_ORDER == BIG_ENDIAN
228 format = __builtin_bswap32(format);
229#endif
230 memcpy(out, &format, 4);
231 return out;
232}
233
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100234static inline struct gl_output_state *
John Kåre Alsaker94659272012-11-13 19:10:18 +0100235get_output_state(struct weston_output *output)
236{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100237 return (struct gl_output_state *)output->renderer_state;
John Kåre Alsaker94659272012-11-13 19:10:18 +0100238}
239
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300240static int
241gl_renderer_create_surface(struct weston_surface *surface);
242
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100243static inline struct gl_surface_state *
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100244get_surface_state(struct weston_surface *surface)
245{
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300246 if (!surface->renderer_state)
247 gl_renderer_create_surface(surface);
248
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100249 return (struct gl_surface_state *)surface->renderer_state;
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100250}
251
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100252static inline struct gl_renderer *
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100253get_renderer(struct weston_compositor *ec)
254{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100255 return (struct gl_renderer *)ec->renderer;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100256}
257
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +0300258static struct egl_image*
259egl_image_create(struct gl_renderer *gr, EGLenum target,
260 EGLClientBuffer buffer, const EGLint *attribs)
261{
262 struct egl_image *img;
263
264 img = zalloc(sizeof *img);
265 img->renderer = gr;
266 img->refcount = 1;
267 img->image = gr->create_image(gr->egl_display, EGL_NO_CONTEXT,
268 target, buffer, attribs);
269
270 if (img->image == EGL_NO_IMAGE_KHR) {
271 free(img);
272 return NULL;
273 }
274
275 return img;
276}
277
278static struct egl_image*
279egl_image_ref(struct egl_image *image)
280{
281 image->refcount++;
282
283 return image;
284}
285
286static int
287egl_image_unref(struct egl_image *image)
288{
289 struct gl_renderer *gr = image->renderer;
290
291 assert(image->refcount > 0);
292
293 image->refcount--;
294 if (image->refcount > 0)
295 return image->refcount;
296
297 gr->destroy_image(gr->egl_display, image->image);
298 free(image);
299
300 return 0;
301}
302
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +0000303static struct dmabuf_image*
304dmabuf_image_create(void)
305{
306 struct dmabuf_image *img;
307
308 img = zalloc(sizeof *img);
309 wl_list_init(&img->link);
310
311 return img;
312}
313
314static void
315dmabuf_image_destroy(struct dmabuf_image *image)
316{
317 int i;
318
319 for (i = 0; i < image->num_images; ++i)
320 egl_image_unref(image->images[i]);
321
322 if (image->dmabuf)
323 linux_dmabuf_buffer_set_user_data(image->dmabuf, NULL, NULL);
324
325 wl_list_remove(&image->link);
326}
327
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400328static const char *
329egl_error_string(EGLint code)
330{
331#define MYERRCODE(x) case x: return #x;
332 switch (code) {
333 MYERRCODE(EGL_SUCCESS)
334 MYERRCODE(EGL_NOT_INITIALIZED)
335 MYERRCODE(EGL_BAD_ACCESS)
336 MYERRCODE(EGL_BAD_ALLOC)
337 MYERRCODE(EGL_BAD_ATTRIBUTE)
338 MYERRCODE(EGL_BAD_CONTEXT)
339 MYERRCODE(EGL_BAD_CONFIG)
340 MYERRCODE(EGL_BAD_CURRENT_SURFACE)
341 MYERRCODE(EGL_BAD_DISPLAY)
342 MYERRCODE(EGL_BAD_SURFACE)
343 MYERRCODE(EGL_BAD_MATCH)
344 MYERRCODE(EGL_BAD_PARAMETER)
345 MYERRCODE(EGL_BAD_NATIVE_PIXMAP)
346 MYERRCODE(EGL_BAD_NATIVE_WINDOW)
347 MYERRCODE(EGL_CONTEXT_LOST)
348 default:
349 return "unknown";
350 }
351#undef MYERRCODE
352}
353
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +0300354static void
Pekka Paalanen326529f2012-11-27 12:25:25 +0200355gl_renderer_print_egl_error_state(void)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400356{
357 EGLint code;
358
359 code = eglGetError();
360 weston_log("EGL error state: %s (0x%04lx)\n",
361 egl_error_string(code), (long)code);
362}
363
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400364#define max(a, b) (((a) > (b)) ? (a) : (b))
365#define min(a, b) (((a) > (b)) ? (b) : (a))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400366
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300367/*
368 * Compute the boundary vertices of the intersection of the global coordinate
369 * aligned rectangle 'rect', and an arbitrary quadrilateral produced from
370 * 'surf_rect' when transformed from surface coordinates into global coordinates.
371 * The vertices are written to 'ex' and 'ey', and the return value is the
372 * number of vertices. Vertices are produced in clockwise winding order.
373 * Guarantees to produce either zero vertices, or 3-8 vertices with non-zero
374 * polygon area.
375 */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400376static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500377calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400378 pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
379{
Sam Spilsbury619859c2013-09-13 10:01:21 +0800380
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300381 struct clip_context ctx;
382 int i, n;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400383 GLfloat min_x, max_x, min_y, max_y;
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300384 struct polygon8 surf = {
385 { surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1 },
386 { surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2 },
387 4
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400388 };
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400389
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300390 ctx.clip.x1 = rect->x1;
391 ctx.clip.y1 = rect->y1;
392 ctx.clip.x2 = rect->x2;
393 ctx.clip.y2 = rect->y2;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400394
395 /* transform surface to screen space: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300396 for (i = 0; i < surf.n; i++)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500397 weston_view_to_global_float(ev, surf.x[i], surf.y[i],
398 &surf.x[i], &surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400399
400 /* find bounding box: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300401 min_x = max_x = surf.x[0];
402 min_y = max_y = surf.y[0];
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400403
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300404 for (i = 1; i < surf.n; i++) {
405 min_x = min(min_x, surf.x[i]);
406 max_x = max(max_x, surf.x[i]);
407 min_y = min(min_y, surf.y[i]);
408 max_y = max(max_y, surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400409 }
410
411 /* First, simple bounding box check to discard early transformed
412 * surface rects that do not intersect with the clip region:
413 */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300414 if ((min_x >= ctx.clip.x2) || (max_x <= ctx.clip.x1) ||
415 (min_y >= ctx.clip.y2) || (max_y <= ctx.clip.y1))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400416 return 0;
417
418 /* Simple case, bounding box edges are parallel to surface edges,
419 * there will be only four edges. We just need to clip the surface
420 * vertices to the clip rect bounds:
421 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500422 if (!ev->transform.enabled)
Sam Spilsbury619859c2013-09-13 10:01:21 +0800423 return clip_simple(&ctx, &surf, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400424
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300425 /* Transformed case: use a general polygon clipping algorithm to
426 * clip the surface rectangle with each side of 'rect'.
427 * The algorithm is Sutherland-Hodgman, as explained in
428 * http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm
429 * but without looking at any of that code.
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400430 */
Sam Spilsbury619859c2013-09-13 10:01:21 +0800431 n = clip_transformed(&ctx, &surf, ex, ey);
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300432
433 if (n < 3)
434 return 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400435
436 return n;
437}
438
Derek Foremanf8180982014-10-16 16:37:02 -0500439static bool
440merge_down(pixman_box32_t *a, pixman_box32_t *b, pixman_box32_t *merge)
441{
442 if (a->x1 == b->x1 && a->x2 == b->x2 && a->y1 == b->y2) {
443 merge->x1 = a->x1;
444 merge->x2 = a->x2;
445 merge->y1 = b->y1;
446 merge->y2 = a->y2;
447 return true;
448 }
449 return false;
450}
451
452static int
453compress_bands(pixman_box32_t *inrects, int nrects,
454 pixman_box32_t **outrects)
455{
456 bool merged;
457 pixman_box32_t *out, merge_rect;
458 int i, j, nout;
459
460 if (!nrects) {
461 *outrects = NULL;
462 return 0;
463 }
464
465 /* nrects is an upper bound - we're not too worried about
466 * allocating a little extra
467 */
468 out = malloc(sizeof(pixman_box32_t) * nrects);
469 out[0] = inrects[0];
470 nout = 1;
471 for (i = 1; i < nrects; i++) {
472 for (j = 0; j < nout; j++) {
473 merged = merge_down(&inrects[i], &out[j], &merge_rect);
474 if (merged) {
475 out[j] = merge_rect;
476 break;
477 }
478 }
479 if (!merged) {
480 out[nout] = inrects[i];
481 nout++;
482 }
483 }
484 *outrects = out;
485 return nout;
486}
487
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400488static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500489texture_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400490 pixman_region32_t *surf_region)
491{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500492 struct gl_surface_state *gs = get_surface_state(ev->surface);
493 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400494 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400495 GLfloat *v, inv_width, inv_height;
496 unsigned int *vtxcnt, nvtx = 0;
497 pixman_box32_t *rects, *surf_rects;
Derek Foremanf8180982014-10-16 16:37:02 -0500498 pixman_box32_t *raw_rects;
499 int i, j, k, nrects, nsurf, raw_nrects;
500 bool used_band_compression;
501 raw_rects = pixman_region32_rectangles(region, &raw_nrects);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400502 surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
503
Derek Foremanf8180982014-10-16 16:37:02 -0500504 if (raw_nrects < 4) {
505 used_band_compression = false;
506 nrects = raw_nrects;
507 rects = raw_rects;
508 } else {
509 nrects = compress_bands(raw_rects, raw_nrects, &rects);
510 used_band_compression = true;
511 }
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400512 /* worst case we can have 8 vertices per rect (ie. clipped into
513 * an octagon):
514 */
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400515 v = wl_array_add(&gr->vertices, nrects * nsurf * 8 * 4 * sizeof *v);
516 vtxcnt = wl_array_add(&gr->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400517
Pekka Paalanen68033ac2012-12-04 15:58:15 +0200518 inv_width = 1.0 / gs->pitch;
Alexander Larsson4ea95522013-05-22 14:41:37 +0200519 inv_height = 1.0 / gs->height;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400520
521 for (i = 0; i < nrects; i++) {
522 pixman_box32_t *rect = &rects[i];
523 for (j = 0; j < nsurf; j++) {
524 pixman_box32_t *surf_rect = &surf_rects[j];
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200525 GLfloat sx, sy, bx, by;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400526 GLfloat ex[8], ey[8]; /* edge points in screen space */
527 int n;
528
529 /* The transformed surface, after clipping to the clip region,
530 * can have as many as eight sides, emitted as a triangle-fan.
531 * The first vertex in the triangle fan can be chosen arbitrarily,
532 * since the area is guaranteed to be convex.
533 *
534 * If a corner of the transformed surface falls outside of the
535 * clip region, instead of emitting one vertex for the corner
536 * of the surface, up to two are emitted for two corresponding
537 * intersection point(s) between the surface and the clip region.
538 *
539 * To do this, we first calculate the (up to eight) points that
540 * form the intersection of the clip rect and the transformed
541 * surface.
542 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500543 n = calculate_edges(ev, rect, surf_rect, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400544 if (n < 3)
545 continue;
546
547 /* emit edge points: */
548 for (k = 0; k < n; k++) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500549 weston_view_from_global_float(ev, ex[k], ey[k],
550 &sx, &sy);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400551 /* position: */
552 *(v++) = ex[k];
553 *(v++) = ey[k];
554 /* texcoord: */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500555 weston_surface_to_buffer_float(ev->surface,
556 sx, sy,
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200557 &bx, &by);
558 *(v++) = bx * inv_width;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +0400559 if (gs->y_inverted) {
560 *(v++) = by * inv_height;
561 } else {
562 *(v++) = (gs->height - by) * inv_height;
563 }
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400564 }
565
566 vtxcnt[nvtx++] = n;
567 }
568 }
569
Derek Foremanf8180982014-10-16 16:37:02 -0500570 if (used_band_compression)
571 free(rects);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400572 return nvtx;
573}
574
575static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500576triangle_fan_debug(struct weston_view *view, int first, int count)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400577{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500578 struct weston_compositor *compositor = view->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100579 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400580 int i;
581 GLushort *buffer;
582 GLushort *index;
583 int nelems;
584 static int color_idx = 0;
585 static const GLfloat color[][4] = {
586 { 1.0, 0.0, 0.0, 1.0 },
587 { 0.0, 1.0, 0.0, 1.0 },
588 { 0.0, 0.0, 1.0, 1.0 },
589 { 1.0, 1.0, 1.0, 1.0 },
590 };
591
592 nelems = (count - 1 + count - 2) * 2;
593
594 buffer = malloc(sizeof(GLushort) * nelems);
595 index = buffer;
596
597 for (i = 1; i < count; i++) {
598 *index++ = first;
599 *index++ = first + i;
600 }
601
602 for (i = 2; i < count; i++) {
603 *index++ = first + i - 1;
604 *index++ = first + i;
605 }
606
John Kåre Alsaker40684142012-11-13 19:10:25 +0100607 glUseProgram(gr->solid_shader.program);
608 glUniform4fv(gr->solid_shader.color_uniform, 1,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400609 color[color_idx++ % ARRAY_LENGTH(color)]);
610 glDrawElements(GL_LINES, nelems, GL_UNSIGNED_SHORT, buffer);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100611 glUseProgram(gr->current_shader->program);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400612 free(buffer);
613}
614
615static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500616repaint_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400617 pixman_region32_t *surf_region)
618{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500619 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400620 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400621 GLfloat *v;
622 unsigned int *vtxcnt;
623 int i, first, nfans;
624
625 /* The final region to be painted is the intersection of
626 * 'region' and 'surf_region'. However, 'region' is in the global
627 * coordinates, and 'surf_region' is in the surface-local
628 * coordinates. texture_region() will iterate over all pairs of
629 * rectangles from both regions, compute the intersection
630 * polygon for each pair, and store it as a triangle fan if
Bryce Harringtonea8fb942016-01-13 18:48:56 -0800631 * it has a non-zero area (at least 3 vertices, actually).
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400632 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500633 nfans = texture_region(ev, region, surf_region);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400634
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400635 v = gr->vertices.data;
636 vtxcnt = gr->vtxcnt.data;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400637
638 /* position: */
639 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
640 glEnableVertexAttribArray(0);
641
642 /* texcoord: */
643 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
644 glEnableVertexAttribArray(1);
645
646 for (i = 0, first = 0; i < nfans; i++) {
647 glDrawArrays(GL_TRIANGLE_FAN, first, vtxcnt[i]);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400648 if (gr->fan_debug)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500649 triangle_fan_debug(ev, first, vtxcnt[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400650 first += vtxcnt[i];
651 }
652
653 glDisableVertexAttribArray(1);
654 glDisableVertexAttribArray(0);
655
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400656 gr->vertices.size = 0;
657 gr->vtxcnt.size = 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400658}
659
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100660static int
661use_output(struct weston_output *output)
662{
663 static int errored;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100664 struct gl_output_state *go = get_output_state(output);
665 struct gl_renderer *gr = get_renderer(output->compositor);
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100666 EGLBoolean ret;
667
668 ret = eglMakeCurrent(gr->egl_display, go->egl_surface,
669 go->egl_surface, gr->egl_context);
670
671 if (ret == EGL_FALSE) {
672 if (errored)
673 return -1;
674 errored = 1;
675 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +0200676 gl_renderer_print_egl_error_state();
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100677 return -1;
678 }
679
680 return 0;
681}
682
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300683static int
684shader_init(struct gl_shader *shader, struct gl_renderer *gr,
685 const char *vertex_source, const char *fragment_source);
686
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400687static void
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300688use_shader(struct gl_renderer *gr, struct gl_shader *shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400689{
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300690 if (!shader->program) {
691 int ret;
692
693 ret = shader_init(shader, gr,
694 shader->vertex_source,
695 shader->fragment_source);
696
697 if (ret < 0)
698 weston_log("warning: failed to compile shader\n");
699 }
700
John Kåre Alsaker40684142012-11-13 19:10:25 +0100701 if (gr->current_shader == shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400702 return;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400703 glUseProgram(shader->program);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100704 gr->current_shader = shader;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400705}
706
707static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100708shader_uniforms(struct gl_shader *shader,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500709 struct weston_view *view,
710 struct weston_output *output)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400711{
712 int i;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500713 struct gl_surface_state *gs = get_surface_state(view->surface);
Jason Ekstrandfb23df72014-10-16 10:55:21 -0500714 struct gl_output_state *go = get_output_state(output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400715
716 glUniformMatrix4fv(shader->proj_uniform,
Jason Ekstrandfb23df72014-10-16 10:55:21 -0500717 1, GL_FALSE, go->output_matrix.d);
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100718 glUniform4fv(shader->color_uniform, 1, gs->color);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500719 glUniform1f(shader->alpha_uniform, view->alpha);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400720
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100721 for (i = 0; i < gs->num_textures; i++)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400722 glUniform1i(shader->tex_uniforms[i], i);
723}
724
725static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500726draw_view(struct weston_view *ev, struct weston_output *output,
727 pixman_region32_t *damage) /* in global coordinates */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400728{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500729 struct weston_compositor *ec = ev->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100730 struct gl_renderer *gr = get_renderer(ec);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500731 struct gl_surface_state *gs = get_surface_state(ev->surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400732 /* repaint bounding region in global coordinates: */
733 pixman_region32_t repaint;
Pekka Paalanenfa79b1d2015-02-18 09:48:59 +0200734 /* opaque region in surface coordinates: */
735 pixman_region32_t surface_opaque;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400736 /* non-opaque region in surface coordinates: */
737 pixman_region32_t surface_blend;
738 GLint filter;
739 int i;
740
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +0200741 /* In case of a runtime switch of renderers, we may not have received
742 * an attach for this surface since the switch. In that case we don't
743 * have a valid buffer or a proper shader set up so skip rendering. */
744 if (!gs->shader)
745 return;
746
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400747 pixman_region32_init(&repaint);
748 pixman_region32_intersect(&repaint,
Pekka Paalanen25c0ca52015-02-19 11:15:33 +0200749 &ev->transform.boundingbox, damage);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500750 pixman_region32_subtract(&repaint, &repaint, &ev->clip);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400751
752 if (!pixman_region32_not_empty(&repaint))
753 goto out;
754
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400755 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
756
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400757 if (gr->fan_debug) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100758 use_shader(gr, &gr->solid_shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500759 shader_uniforms(&gr->solid_shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400760 }
761
John Kåre Alsaker40684142012-11-13 19:10:25 +0100762 use_shader(gr, gs->shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500763 shader_uniforms(gs->shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400764
Jason Ekstranda7af7042013-10-12 22:38:11 -0500765 if (ev->transform.enabled || output->zoom.active ||
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200766 output->current_scale != ev->surface->buffer_viewport.buffer.scale)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400767 filter = GL_LINEAR;
768 else
769 filter = GL_NEAREST;
770
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100771 for (i = 0; i < gs->num_textures; i++) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400772 glActiveTexture(GL_TEXTURE0 + i);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100773 glBindTexture(gs->target, gs->textures[i]);
774 glTexParameteri(gs->target, GL_TEXTURE_MIN_FILTER, filter);
775 glTexParameteri(gs->target, GL_TEXTURE_MAG_FILTER, filter);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400776 }
777
778 /* blended region is whole surface minus opaque region: */
779 pixman_region32_init_rect(&surface_blend, 0, 0,
Jason Ekstrand918f2dd2013-12-02 21:01:53 -0600780 ev->surface->width, ev->surface->height);
Pekka Paalanenfa79b1d2015-02-18 09:48:59 +0200781 if (ev->geometry.scissor_enabled)
782 pixman_region32_intersect(&surface_blend, &surface_blend,
783 &ev->geometry.scissor);
784 pixman_region32_subtract(&surface_blend, &surface_blend,
785 &ev->surface->opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400786
Jason Ekstranda7af7042013-10-12 22:38:11 -0500787 /* XXX: Should we be using ev->transform.opaque here? */
Pekka Paalanenfa79b1d2015-02-18 09:48:59 +0200788 pixman_region32_init(&surface_opaque);
789 if (ev->geometry.scissor_enabled)
790 pixman_region32_intersect(&surface_opaque,
791 &ev->surface->opaque,
792 &ev->geometry.scissor);
793 else
794 pixman_region32_copy(&surface_opaque, &ev->surface->opaque);
795
796 if (pixman_region32_not_empty(&surface_opaque)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100797 if (gs->shader == &gr->texture_shader_rgba) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400798 /* Special case for RGBA textures with possibly
799 * bad data in alpha channel: use the shader
800 * that forces texture alpha = 1.0.
801 * Xwayland surfaces need this.
802 */
John Kåre Alsaker40684142012-11-13 19:10:25 +0100803 use_shader(gr, &gr->texture_shader_rgbx);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500804 shader_uniforms(&gr->texture_shader_rgbx, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400805 }
806
Jason Ekstranda7af7042013-10-12 22:38:11 -0500807 if (ev->alpha < 1.0)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400808 glEnable(GL_BLEND);
809 else
810 glDisable(GL_BLEND);
811
Pekka Paalanenfa79b1d2015-02-18 09:48:59 +0200812 repaint_region(ev, &repaint, &surface_opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400813 }
814
815 if (pixman_region32_not_empty(&surface_blend)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100816 use_shader(gr, gs->shader);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400817 glEnable(GL_BLEND);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500818 repaint_region(ev, &repaint, &surface_blend);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400819 }
820
821 pixman_region32_fini(&surface_blend);
Pekka Paalanenfa79b1d2015-02-18 09:48:59 +0200822 pixman_region32_fini(&surface_opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400823
824out:
825 pixman_region32_fini(&repaint);
826}
827
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400828static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500829repaint_views(struct weston_output *output, pixman_region32_t *damage)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400830{
831 struct weston_compositor *compositor = output->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500832 struct weston_view *view;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400833
Jason Ekstranda7af7042013-10-12 22:38:11 -0500834 wl_list_for_each_reverse(view, &compositor->view_list, link)
835 if (view->plane == &compositor->primary_plane)
836 draw_view(view, output, damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400837}
838
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500839static void
Jason Ekstrande5512d42014-02-04 21:36:38 -0600840draw_output_border_texture(struct gl_output_state *go,
841 enum gl_renderer_border_side side,
842 int32_t x, int32_t y,
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500843 int32_t width, int32_t height)
844{
Jason Ekstrande5512d42014-02-04 21:36:38 -0600845 struct gl_border_image *img = &go->borders[side];
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500846 static GLushort indices [] = { 0, 1, 3, 3, 1, 2 };
847
848 if (!img->data) {
849 if (img->tex) {
850 glDeleteTextures(1, &img->tex);
851 img->tex = 0;
852 }
853
854 return;
855 }
856
857 if (!img->tex) {
858 glGenTextures(1, &img->tex);
859 glBindTexture(GL_TEXTURE_2D, img->tex);
860
861 glTexParameteri(GL_TEXTURE_2D,
862 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
863 glTexParameteri(GL_TEXTURE_2D,
864 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
865 glTexParameteri(GL_TEXTURE_2D,
866 GL_TEXTURE_MIN_FILTER, GL_NEAREST);
867 glTexParameteri(GL_TEXTURE_2D,
868 GL_TEXTURE_MAG_FILTER, GL_NEAREST);
869 } else {
870 glBindTexture(GL_TEXTURE_2D, img->tex);
871 }
872
Jason Ekstrande5512d42014-02-04 21:36:38 -0600873 if (go->border_status & (1 << side)) {
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500874 glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0);
875 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
876 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500877 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
878 img->tex_width, img->height, 0,
879 GL_BGRA_EXT, GL_UNSIGNED_BYTE, img->data);
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500880 }
881
882 GLfloat texcoord[] = {
883 0.0f, 0.0f,
884 (GLfloat)img->width / (GLfloat)img->tex_width, 0.0f,
885 (GLfloat)img->width / (GLfloat)img->tex_width, 1.0f,
886 0.0f, 1.0f,
887 };
888
889 GLfloat verts[] = {
890 x, y,
891 x + width, y,
892 x + width, y + height,
893 x, y + height
894 };
895
896 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
897 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord);
898 glEnableVertexAttribArray(0);
899 glEnableVertexAttribArray(1);
900
901 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
902
903 glDisableVertexAttribArray(1);
904 glDisableVertexAttribArray(0);
905}
906
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -0600907static int
908output_has_borders(struct weston_output *output)
909{
910 struct gl_output_state *go = get_output_state(output);
911
912 return go->borders[GL_RENDERER_BORDER_TOP].data ||
913 go->borders[GL_RENDERER_BORDER_RIGHT].data ||
914 go->borders[GL_RENDERER_BORDER_BOTTOM].data ||
915 go->borders[GL_RENDERER_BORDER_LEFT].data;
916}
917
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500918static void
Jason Ekstrande5512d42014-02-04 21:36:38 -0600919draw_output_borders(struct weston_output *output,
920 enum gl_border_status border_status)
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500921{
922 struct gl_output_state *go = get_output_state(output);
923 struct gl_renderer *gr = get_renderer(output->compositor);
924 struct gl_shader *shader = &gr->texture_shader_rgba;
Jason Ekstrand00b84282013-10-27 22:24:59 -0500925 struct gl_border_image *top, *bottom, *left, *right;
926 struct weston_matrix matrix;
927 int full_width, full_height;
928
Jason Ekstrande5512d42014-02-04 21:36:38 -0600929 if (border_status == BORDER_STATUS_CLEAN)
930 return; /* Clean. Nothing to do. */
931
Jason Ekstrand00b84282013-10-27 22:24:59 -0500932 top = &go->borders[GL_RENDERER_BORDER_TOP];
933 bottom = &go->borders[GL_RENDERER_BORDER_BOTTOM];
934 left = &go->borders[GL_RENDERER_BORDER_LEFT];
935 right = &go->borders[GL_RENDERER_BORDER_RIGHT];
936
937 full_width = output->current_mode->width + left->width + right->width;
938 full_height = output->current_mode->height + top->height + bottom->height;
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500939
940 glDisable(GL_BLEND);
941 use_shader(gr, shader);
942
Jason Ekstrand00b84282013-10-27 22:24:59 -0500943 glViewport(0, 0, full_width, full_height);
944
945 weston_matrix_init(&matrix);
946 weston_matrix_translate(&matrix, -full_width/2.0, -full_height/2.0, 0);
947 weston_matrix_scale(&matrix, 2.0/full_width, -2.0/full_height, 1);
948 glUniformMatrix4fv(shader->proj_uniform, 1, GL_FALSE, matrix.d);
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500949
950 glUniform1i(shader->tex_uniforms[0], 0);
951 glUniform1f(shader->alpha_uniform, 1);
952 glActiveTexture(GL_TEXTURE0);
953
Jason Ekstrande5512d42014-02-04 21:36:38 -0600954 if (border_status & BORDER_TOP_DIRTY)
955 draw_output_border_texture(go, GL_RENDERER_BORDER_TOP,
956 0, 0,
957 full_width, top->height);
958 if (border_status & BORDER_LEFT_DIRTY)
959 draw_output_border_texture(go, GL_RENDERER_BORDER_LEFT,
960 0, top->height,
961 left->width, output->current_mode->height);
962 if (border_status & BORDER_RIGHT_DIRTY)
963 draw_output_border_texture(go, GL_RENDERER_BORDER_RIGHT,
964 full_width - right->width, top->height,
965 right->width, output->current_mode->height);
966 if (border_status & BORDER_BOTTOM_DIRTY)
967 draw_output_border_texture(go, GL_RENDERER_BORDER_BOTTOM,
968 0, full_height - bottom->height,
969 full_width, bottom->height);
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500970}
John Kåre Alsaker44154502012-11-13 19:10:20 +0100971
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400972static void
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -0600973output_get_border_damage(struct weston_output *output,
974 enum gl_border_status border_status,
975 pixman_region32_t *damage)
976{
977 struct gl_output_state *go = get_output_state(output);
978 struct gl_border_image *top, *bottom, *left, *right;
979 int full_width, full_height;
980
981 if (border_status == BORDER_STATUS_CLEAN)
982 return; /* Clean. Nothing to do. */
983
984 top = &go->borders[GL_RENDERER_BORDER_TOP];
985 bottom = &go->borders[GL_RENDERER_BORDER_BOTTOM];
986 left = &go->borders[GL_RENDERER_BORDER_LEFT];
987 right = &go->borders[GL_RENDERER_BORDER_RIGHT];
988
989 full_width = output->current_mode->width + left->width + right->width;
990 full_height = output->current_mode->height + top->height + bottom->height;
991 if (border_status & BORDER_TOP_DIRTY)
992 pixman_region32_union_rect(damage, damage,
993 0, 0,
994 full_width, top->height);
995 if (border_status & BORDER_LEFT_DIRTY)
996 pixman_region32_union_rect(damage, damage,
997 0, top->height,
998 left->width, output->current_mode->height);
999 if (border_status & BORDER_RIGHT_DIRTY)
1000 pixman_region32_union_rect(damage, damage,
1001 full_width - right->width, top->height,
1002 right->width, output->current_mode->height);
1003 if (border_status & BORDER_BOTTOM_DIRTY)
1004 pixman_region32_union_rect(damage, damage,
1005 0, full_height - bottom->height,
1006 full_width, bottom->height);
1007}
1008
1009static void
Jason Ekstrande5512d42014-02-04 21:36:38 -06001010output_get_damage(struct weston_output *output,
1011 pixman_region32_t *buffer_damage, uint32_t *border_damage)
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001012{
1013 struct gl_output_state *go = get_output_state(output);
1014 struct gl_renderer *gr = get_renderer(output->compositor);
1015 EGLint buffer_age = 0;
1016 EGLBoolean ret;
1017 int i;
1018
1019 if (gr->has_egl_buffer_age) {
1020 ret = eglQuerySurface(gr->egl_display, go->egl_surface,
1021 EGL_BUFFER_AGE_EXT, &buffer_age);
1022 if (ret == EGL_FALSE) {
1023 weston_log("buffer age query failed.\n");
1024 gl_renderer_print_egl_error_state();
1025 }
1026 }
1027
Jason Ekstrande5512d42014-02-04 21:36:38 -06001028 if (buffer_age == 0 || buffer_age - 1 > BUFFER_DAMAGE_COUNT) {
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001029 pixman_region32_copy(buffer_damage, &output->region);
Jason Ekstrande5512d42014-02-04 21:36:38 -06001030 *border_damage = BORDER_ALL_DIRTY;
1031 } else {
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001032 for (i = 0; i < buffer_age - 1; i++)
Derek Foreman4c582662014-10-09 18:39:44 -05001033 *border_damage |= go->border_damage[(go->buffer_damage_index + i) % BUFFER_DAMAGE_COUNT];
Jason Ekstrande5512d42014-02-04 21:36:38 -06001034
1035 if (*border_damage & BORDER_SIZE_CHANGED) {
1036 /* If we've had a resize, we have to do a full
1037 * repaint. */
1038 *border_damage |= BORDER_ALL_DIRTY;
1039 pixman_region32_copy(buffer_damage, &output->region);
1040 } else {
1041 for (i = 0; i < buffer_age - 1; i++)
1042 pixman_region32_union(buffer_damage,
1043 buffer_damage,
Derek Foreman4c582662014-10-09 18:39:44 -05001044 &go->buffer_damage[(go->buffer_damage_index + i) % BUFFER_DAMAGE_COUNT]);
Jason Ekstrande5512d42014-02-04 21:36:38 -06001045 }
1046 }
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001047}
1048
1049static void
1050output_rotate_damage(struct weston_output *output,
Jason Ekstrande5512d42014-02-04 21:36:38 -06001051 pixman_region32_t *output_damage,
1052 enum gl_border_status border_status)
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001053{
1054 struct gl_output_state *go = get_output_state(output);
1055 struct gl_renderer *gr = get_renderer(output->compositor);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001056
1057 if (!gr->has_egl_buffer_age)
1058 return;
1059
Derek Foreman4c582662014-10-09 18:39:44 -05001060 go->buffer_damage_index += BUFFER_DAMAGE_COUNT - 1;
1061 go->buffer_damage_index %= BUFFER_DAMAGE_COUNT;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001062
Derek Foreman4c582662014-10-09 18:39:44 -05001063 pixman_region32_copy(&go->buffer_damage[go->buffer_damage_index], output_damage);
1064 go->border_damage[go->buffer_damage_index] = border_status;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001065}
1066
Derek Foremanc4cfe852015-05-15 12:12:40 -05001067/* NOTE: We now allow falling back to ARGB gl visuals when XRGB is
1068 * unavailable, so we're assuming the background has no transparency
1069 * and that everything with a blend, like drop shadows, will have something
1070 * opaque (like the background) drawn underneath it.
1071 *
1072 * Depending on the underlying hardware, violating that assumption could
1073 * result in seeing through to another display plane.
1074 */
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001075static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001076gl_renderer_repaint_output(struct weston_output *output,
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001077 pixman_region32_t *output_damage)
1078{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001079 struct gl_output_state *go = get_output_state(output);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001080 struct weston_compositor *compositor = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001081 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001082 EGLBoolean ret;
1083 static int errored;
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -06001084 int i, nrects, buffer_height;
1085 EGLint *egl_damage, *d;
1086 pixman_box32_t *rects;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001087 pixman_region32_t buffer_damage, total_damage;
Jason Ekstrande5512d42014-02-04 21:36:38 -06001088 enum gl_border_status border_damage = BORDER_STATUS_CLEAN;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001089
Jason Ekstrandae0c6e32014-10-16 10:55:20 -05001090 if (use_output(output) < 0)
1091 return;
1092
Jason Ekstrand00b84282013-10-27 22:24:59 -05001093 /* Calculate the viewport */
1094 glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width,
1095 go->borders[GL_RENDERER_BORDER_BOTTOM].height,
1096 output->current_mode->width,
1097 output->current_mode->height);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001098
Jason Ekstrandfb23df72014-10-16 10:55:21 -05001099 /* Calculate the global GL matrix */
1100 go->output_matrix = output->matrix;
1101 weston_matrix_translate(&go->output_matrix,
1102 -(output->current_mode->width / 2.0),
1103 -(output->current_mode->height / 2.0), 0);
1104 weston_matrix_scale(&go->output_matrix,
1105 2.0 / output->current_mode->width,
1106 -2.0 / output->current_mode->height, 1);
1107
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001108 /* if debugging, redraw everything outside the damage to clean up
1109 * debug lines from the previous draw on this buffer:
1110 */
Kristian Høgsberg8799d412013-05-07 10:50:09 -04001111 if (gr->fan_debug) {
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001112 pixman_region32_t undamaged;
1113 pixman_region32_init(&undamaged);
1114 pixman_region32_subtract(&undamaged, &output->region,
1115 output_damage);
Kristian Høgsberg8799d412013-05-07 10:50:09 -04001116 gr->fan_debug = 0;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001117 repaint_views(output, &undamaged);
Kristian Høgsberg8799d412013-05-07 10:50:09 -04001118 gr->fan_debug = 1;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001119 pixman_region32_fini(&undamaged);
1120 }
1121
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +02001122 pixman_region32_init(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001123 pixman_region32_init(&buffer_damage);
1124
Jason Ekstrande5512d42014-02-04 21:36:38 -06001125 output_get_damage(output, &buffer_damage, &border_damage);
1126 output_rotate_damage(output, output_damage, go->border_status);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001127
1128 pixman_region32_union(&total_damage, &buffer_damage, output_damage);
Jason Ekstrande5512d42014-02-04 21:36:38 -06001129 border_damage |= go->border_status;
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +03001130
Jason Ekstranda7af7042013-10-12 22:38:11 -05001131 repaint_views(output, &total_damage);
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +02001132
1133 pixman_region32_fini(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001134 pixman_region32_fini(&buffer_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001135
Jason Ekstrande5512d42014-02-04 21:36:38 -06001136 draw_output_borders(output, border_damage);
John Kåre Alsaker44154502012-11-13 19:10:20 +01001137
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001138 pixman_region32_copy(&output->previous_damage, output_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001139 wl_signal_emit(&output->frame_signal, output);
1140
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -06001141 if (gr->swap_buffers_with_damage) {
1142 pixman_region32_init(&buffer_damage);
1143 weston_transformed_region(output->width, output->height,
1144 output->transform,
1145 output->current_scale,
1146 output_damage, &buffer_damage);
1147
1148 if (output_has_borders(output)) {
1149 pixman_region32_translate(&buffer_damage,
1150 go->borders[GL_RENDERER_BORDER_LEFT].width,
1151 go->borders[GL_RENDERER_BORDER_TOP].height);
1152 output_get_border_damage(output, go->border_status,
1153 &buffer_damage);
1154 }
1155
1156 rects = pixman_region32_rectangles(&buffer_damage, &nrects);
1157 egl_damage = malloc(nrects * 4 * sizeof(EGLint));
1158
1159 buffer_height = go->borders[GL_RENDERER_BORDER_TOP].height +
1160 output->current_mode->height +
1161 go->borders[GL_RENDERER_BORDER_BOTTOM].height;
1162
1163 d = egl_damage;
1164 for (i = 0; i < nrects; ++i) {
1165 *d++ = rects[i].x1;
1166 *d++ = buffer_height - rects[i].y2;
1167 *d++ = rects[i].x2 - rects[i].x1;
1168 *d++ = rects[i].y2 - rects[i].y1;
1169 }
1170 ret = gr->swap_buffers_with_damage(gr->egl_display,
1171 go->egl_surface,
1172 egl_damage, nrects);
1173 free(egl_damage);
1174 pixman_region32_fini(&buffer_damage);
1175 } else {
1176 ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
1177 }
Jason Ekstrand8e96f9e2014-02-04 21:36:39 -06001178
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001179 if (ret == EGL_FALSE && !errored) {
1180 errored = 1;
1181 weston_log("Failed in eglSwapBuffers.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001182 gl_renderer_print_egl_error_state();
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001183 }
1184
Jason Ekstrande5512d42014-02-04 21:36:38 -06001185 go->border_status = BORDER_STATUS_CLEAN;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001186}
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001187
John Kåre Alsakera95b2d62012-11-13 19:10:21 +01001188static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001189gl_renderer_read_pixels(struct weston_output *output,
John Kåre Alsakera95b2d62012-11-13 19:10:21 +01001190 pixman_format_code_t format, void *pixels,
1191 uint32_t x, uint32_t y,
1192 uint32_t width, uint32_t height)
1193{
1194 GLenum gl_format;
Jason Ekstrand701f6362014-04-02 19:53:59 -05001195 struct gl_output_state *go = get_output_state(output);
1196
1197 x += go->borders[GL_RENDERER_BORDER_LEFT].width;
1198 y += go->borders[GL_RENDERER_BORDER_BOTTOM].height;
John Kåre Alsakera95b2d62012-11-13 19:10:21 +01001199
1200 switch (format) {
1201 case PIXMAN_a8r8g8b8:
1202 gl_format = GL_BGRA_EXT;
1203 break;
1204 case PIXMAN_a8b8g8r8:
1205 gl_format = GL_RGBA;
1206 break;
1207 default:
1208 return -1;
1209 }
1210
1211 if (use_output(output) < 0)
1212 return -1;
1213
1214 glPixelStorei(GL_PACK_ALIGNMENT, 1);
1215 glReadPixels(x, y, width, height, gl_format,
1216 GL_UNSIGNED_BYTE, pixels);
1217
1218 return 0;
1219}
1220
Kristian Høgsbergfa1be022012-09-05 22:49:55 -04001221static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001222gl_renderer_flush_damage(struct weston_surface *surface)
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001223{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001224 struct gl_renderer *gr = get_renderer(surface->compositor);
1225 struct gl_surface_state *gs = get_surface_state(surface);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001226 struct weston_buffer *buffer = gs->buffer_ref.buffer;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001227 struct weston_view *view;
Derek Foreman97746792015-11-18 16:32:28 -06001228 bool texture_used;
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001229 pixman_box32_t *rectangles;
1230 void *data;
1231 int i, n;
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001232
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001233 pixman_region32_union(&gs->texture_damage,
1234 &gs->texture_damage, &surface->damage);
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001235
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001236 if (!buffer)
1237 return;
1238
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001239 /* Avoid upload, if the texture won't be used this time.
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001240 * We still accumulate the damage in texture_damage, and
1241 * hold the reference to the buffer, in case the surface
1242 * migrates back to the primary plane.
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001243 */
Derek Foreman97746792015-11-18 16:32:28 -06001244 texture_used = false;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001245 wl_list_for_each(view, &surface->views, surface_link) {
1246 if (view->plane == &surface->compositor->primary_plane) {
Derek Foreman97746792015-11-18 16:32:28 -06001247 texture_used = true;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001248 break;
1249 }
1250 }
1251 if (!texture_used)
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001252 return;
1253
Ander Conselvan de Oliveira895b1fd2013-11-19 15:22:05 +02001254 if (!pixman_region32_not_empty(&gs->texture_damage) &&
1255 !gs->needs_full_upload)
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001256 goto done;
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001257
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001258 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001259
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001260 if (!gr->has_unpack_subimage) {
Neil Robertse5051712013-11-13 15:44:06 +00001261 wl_shm_buffer_begin_access(buffer->shm_buffer);
Neil Roberts4d085e72014-04-07 15:01:01 +01001262 glTexImage2D(GL_TEXTURE_2D, 0, gs->gl_format,
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001263 gs->pitch, buffer->height, 0,
Neil Roberts4d085e72014-04-07 15:01:01 +01001264 gs->gl_format, gs->gl_pixel_type,
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001265 wl_shm_buffer_get_data(buffer->shm_buffer));
Neil Robertse5051712013-11-13 15:44:06 +00001266 wl_shm_buffer_end_access(buffer->shm_buffer);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001267
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001268 goto done;
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001269 }
1270
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -07001271 glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, gs->pitch);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001272 data = wl_shm_buffer_get_data(buffer->shm_buffer);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +03001273
1274 if (gs->needs_full_upload) {
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -07001275 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
1276 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
Neil Robertse5051712013-11-13 15:44:06 +00001277 wl_shm_buffer_begin_access(buffer->shm_buffer);
Neil Roberts4d085e72014-04-07 15:01:01 +01001278 glTexImage2D(GL_TEXTURE_2D, 0, gs->gl_format,
Neil Roberts39a443f2014-04-04 16:24:54 +01001279 gs->pitch, buffer->height, 0,
Neil Roberts4d085e72014-04-07 15:01:01 +01001280 gs->gl_format, gs->gl_pixel_type, data);
Neil Robertse5051712013-11-13 15:44:06 +00001281 wl_shm_buffer_end_access(buffer->shm_buffer);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +03001282 goto done;
1283 }
1284
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001285 rectangles = pixman_region32_rectangles(&gs->texture_damage, &n);
Neil Robertse5051712013-11-13 15:44:06 +00001286 wl_shm_buffer_begin_access(buffer->shm_buffer);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001287 for (i = 0; i < n; i++) {
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +02001288 pixman_box32_t r;
1289
1290 r = weston_surface_to_buffer_rect(surface, rectangles[i]);
1291
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -07001292 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, r.x1);
1293 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, r.y1);
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +02001294 glTexSubImage2D(GL_TEXTURE_2D, 0, r.x1, r.y1,
1295 r.x2 - r.x1, r.y2 - r.y1,
Neil Roberts4d085e72014-04-07 15:01:01 +01001296 gs->gl_format, gs->gl_pixel_type, data);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001297 }
Neil Robertse5051712013-11-13 15:44:06 +00001298 wl_shm_buffer_end_access(buffer->shm_buffer);
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001299
1300done:
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001301 pixman_region32_fini(&gs->texture_damage);
1302 pixman_region32_init(&gs->texture_damage);
Derek Foreman4c11fe72015-11-18 16:32:27 -06001303 gs->needs_full_upload = false;
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001304
1305 weston_buffer_reference(&gs->buffer_ref, NULL);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001306}
1307
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001308static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001309ensure_textures(struct gl_surface_state *gs, int num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001310{
1311 int i;
1312
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001313 if (num_textures <= gs->num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001314 return;
1315
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001316 for (i = gs->num_textures; i < num_textures; i++) {
1317 glGenTextures(1, &gs->textures[i]);
1318 glBindTexture(gs->target, gs->textures[i]);
1319 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001320 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001321 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001322 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1323 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001324 gs->num_textures = num_textures;
1325 glBindTexture(gs->target, 0);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001326}
1327
Kristian Høgsbergfa1be022012-09-05 22:49:55 -04001328static void
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001329gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
1330 struct wl_shm_buffer *shm_buffer)
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);
Neil Roberts4d085e72014-04-07 15:01:01 +01001335 GLenum gl_format, gl_pixel_type;
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001336 int pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001337
1338 buffer->shm_buffer = shm_buffer;
1339 buffer->width = wl_shm_buffer_get_width(shm_buffer);
1340 buffer->height = wl_shm_buffer_get_height(shm_buffer);
1341
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001342 switch (wl_shm_buffer_get_format(shm_buffer)) {
1343 case WL_SHM_FORMAT_XRGB8888:
1344 gs->shader = &gr->texture_shader_rgbx;
1345 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
Neil Roberts4d085e72014-04-07 15:01:01 +01001346 gl_format = GL_BGRA_EXT;
1347 gl_pixel_type = GL_UNSIGNED_BYTE;
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001348 break;
1349 case WL_SHM_FORMAT_ARGB8888:
1350 gs->shader = &gr->texture_shader_rgba;
1351 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
Neil Roberts4d085e72014-04-07 15:01:01 +01001352 gl_format = GL_BGRA_EXT;
1353 gl_pixel_type = GL_UNSIGNED_BYTE;
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001354 break;
1355 case WL_SHM_FORMAT_RGB565:
1356 gs->shader = &gr->texture_shader_rgbx;
1357 pitch = wl_shm_buffer_get_stride(shm_buffer) / 2;
Neil Roberts4d085e72014-04-07 15:01:01 +01001358 gl_format = GL_RGB;
1359 gl_pixel_type = GL_UNSIGNED_SHORT_5_6_5;
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001360 break;
1361 default:
Neil Roberts4d085e72014-04-07 15:01:01 +01001362 weston_log("warning: unknown shm buffer format: %08x\n",
1363 wl_shm_buffer_get_format(shm_buffer));
1364 return;
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001365 }
1366
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001367 /* Only allocate a texture if it doesn't match existing one.
1368 * If a switch from DRM allocated buffer to a SHM buffer is
1369 * happening, we need to allocate a new texture buffer. */
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001370 if (pitch != gs->pitch ||
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001371 buffer->height != gs->height ||
Neil Roberts4d085e72014-04-07 15:01:01 +01001372 gl_format != gs->gl_format ||
1373 gl_pixel_type != gs->gl_pixel_type ||
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001374 gs->buffer_type != BUFFER_TYPE_SHM) {
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001375 gs->pitch = pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001376 gs->height = buffer->height;
1377 gs->target = GL_TEXTURE_2D;
Neil Roberts4d085e72014-04-07 15:01:01 +01001378 gs->gl_format = gl_format;
1379 gs->gl_pixel_type = gl_pixel_type;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001380 gs->buffer_type = BUFFER_TYPE_SHM;
Derek Foreman4c11fe72015-11-18 16:32:27 -06001381 gs->needs_full_upload = true;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001382 gs->y_inverted = 1;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001383
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001384 gs->surface = es;
1385
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001386 ensure_textures(gs, 1);
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001387 }
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001388}
1389
1390static void
1391gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
1392 uint32_t format)
1393{
1394 struct weston_compositor *ec = es->compositor;
1395 struct gl_renderer *gr = get_renderer(ec);
1396 struct gl_surface_state *gs = get_surface_state(es);
1397 EGLint attribs[3];
1398 int i, num_planes;
1399
1400 buffer->legacy_buffer = (struct wl_buffer *)buffer->resource;
1401 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1402 EGL_WIDTH, &buffer->width);
1403 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1404 EGL_HEIGHT, &buffer->height);
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001405 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1406 EGL_WAYLAND_Y_INVERTED_WL, &buffer->y_inverted);
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001407
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +03001408 for (i = 0; i < gs->num_images; i++) {
1409 egl_image_unref(gs->images[i]);
1410 gs->images[i] = NULL;
1411 }
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001412 gs->num_images = 0;
1413 gs->target = GL_TEXTURE_2D;
1414 switch (format) {
1415 case EGL_TEXTURE_RGB:
1416 case EGL_TEXTURE_RGBA:
1417 default:
1418 num_planes = 1;
1419 gs->shader = &gr->texture_shader_rgba;
1420 break;
1421 case EGL_TEXTURE_EXTERNAL_WL:
1422 num_planes = 1;
1423 gs->target = GL_TEXTURE_EXTERNAL_OES;
1424 gs->shader = &gr->texture_shader_egl_external;
1425 break;
1426 case EGL_TEXTURE_Y_UV_WL:
1427 num_planes = 2;
1428 gs->shader = &gr->texture_shader_y_uv;
1429 break;
1430 case EGL_TEXTURE_Y_U_V_WL:
1431 num_planes = 3;
1432 gs->shader = &gr->texture_shader_y_u_v;
1433 break;
1434 case EGL_TEXTURE_Y_XUXV_WL:
1435 num_planes = 2;
1436 gs->shader = &gr->texture_shader_y_xuxv;
1437 break;
1438 }
1439
1440 ensure_textures(gs, num_planes);
1441 for (i = 0; i < num_planes; i++) {
1442 attribs[0] = EGL_WAYLAND_PLANE_WL;
1443 attribs[1] = i;
1444 attribs[2] = EGL_NONE;
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +03001445 gs->images[i] = egl_image_create(gr,
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001446 EGL_WAYLAND_BUFFER_WL,
1447 buffer->legacy_buffer,
1448 attribs);
1449 if (!gs->images[i]) {
1450 weston_log("failed to create img for plane %d\n", i);
1451 continue;
1452 }
1453 gs->num_images++;
1454
1455 glActiveTexture(GL_TEXTURE0 + i);
1456 glBindTexture(gs->target, gs->textures[i]);
1457 gr->image_target_texture_2d(gs->target,
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +03001458 gs->images[i]->image);
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001459 }
1460
1461 gs->pitch = buffer->width;
1462 gs->height = buffer->height;
1463 gs->buffer_type = BUFFER_TYPE_EGL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001464 gs->y_inverted = buffer->y_inverted;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001465}
1466
1467static void
Pekka Paalanena3525802014-06-12 16:49:29 +03001468gl_renderer_destroy_dmabuf(struct linux_dmabuf_buffer *dmabuf)
1469{
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001470 struct dmabuf_image *image = dmabuf->user_data;
Pekka Paalanena3525802014-06-12 16:49:29 +03001471
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001472 dmabuf_image_destroy(image);
Pekka Paalanena3525802014-06-12 16:49:29 +03001473}
1474
1475static struct egl_image *
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001476import_simple_dmabuf(struct gl_renderer *gr,
1477 struct dmabuf_attributes *attributes)
Pekka Paalanena3525802014-06-12 16:49:29 +03001478{
1479 struct egl_image *image;
1480 EGLint attribs[30];
1481 int atti = 0;
1482
Pekka Paalanena3525802014-06-12 16:49:29 +03001483 /* This requires the Mesa commit in
1484 * Mesa 10.3 (08264e5dad4df448e7718e782ad9077902089a07) or
1485 * Mesa 10.2.7 (55d28925e6109a4afd61f109e845a8a51bd17652).
1486 * Otherwise Mesa closes the fd behind our back and re-importing
1487 * will fail.
1488 * https://bugs.freedesktop.org/show_bug.cgi?id=76188
1489 */
1490
1491 attribs[atti++] = EGL_WIDTH;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001492 attribs[atti++] = attributes->width;
Pekka Paalanena3525802014-06-12 16:49:29 +03001493 attribs[atti++] = EGL_HEIGHT;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001494 attribs[atti++] = attributes->height;
Pekka Paalanena3525802014-06-12 16:49:29 +03001495 attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001496 attribs[atti++] = attributes->format;
Pekka Paalanena3525802014-06-12 16:49:29 +03001497 /* XXX: Add modifier here when supported */
1498
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001499 if (attributes->n_planes > 0) {
Pekka Paalanena3525802014-06-12 16:49:29 +03001500 attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001501 attribs[atti++] = attributes->fd[0];
Pekka Paalanena3525802014-06-12 16:49:29 +03001502 attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001503 attribs[atti++] = attributes->offset[0];
Pekka Paalanena3525802014-06-12 16:49:29 +03001504 attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001505 attribs[atti++] = attributes->stride[0];
Pekka Paalanena3525802014-06-12 16:49:29 +03001506 }
1507
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001508 if (attributes->n_planes > 1) {
Pekka Paalanena3525802014-06-12 16:49:29 +03001509 attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001510 attribs[atti++] = attributes->fd[1];
Pekka Paalanena3525802014-06-12 16:49:29 +03001511 attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001512 attribs[atti++] = attributes->offset[1];
Pekka Paalanena3525802014-06-12 16:49:29 +03001513 attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001514 attribs[atti++] = attributes->stride[1];
Pekka Paalanena3525802014-06-12 16:49:29 +03001515 }
1516
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001517 if (attributes->n_planes > 2) {
Pekka Paalanena3525802014-06-12 16:49:29 +03001518 attribs[atti++] = EGL_DMA_BUF_PLANE2_FD_EXT;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001519 attribs[atti++] = attributes->fd[2];
Pekka Paalanena3525802014-06-12 16:49:29 +03001520 attribs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001521 attribs[atti++] = attributes->offset[2];
Pekka Paalanena3525802014-06-12 16:49:29 +03001522 attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001523 attribs[atti++] = attributes->stride[2];
Pekka Paalanena3525802014-06-12 16:49:29 +03001524 }
1525
1526 attribs[atti++] = EGL_NONE;
1527
1528 image = egl_image_create(gr, EGL_LINUX_DMA_BUF_EXT, NULL,
1529 attribs);
1530
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001531 return image;
1532}
Pekka Paalanena3525802014-06-12 16:49:29 +03001533
Emmanuel Gil Peyrotbc35fda2016-01-11 19:04:35 +00001534/* The kernel header drm_fourcc.h defines the DRM formats below. We duplicate
1535 * some of the definitions here so that building Weston won't require
1536 * bleeding-edge kernel headers.
1537 */
1538#ifndef DRM_FORMAT_R8
1539#define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ') /* [7:0] R */
1540#endif
1541
1542#ifndef DRM_FORMAT_GR88
1543#define DRM_FORMAT_GR88 fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 little endian */
1544#endif
1545
1546struct yuv_format_descriptor yuv_formats[] = {
1547 {
1548 .format = DRM_FORMAT_YUYV,
1549 .input_planes = 1,
1550 .output_planes = 2,
1551 .texture_type = EGL_TEXTURE_Y_XUXV_WL,
1552 {{
1553 .width_divisor = 1,
1554 .height_divisor = 1,
1555 .format = DRM_FORMAT_GR88,
1556 .plane_index = 0
1557 }, {
1558 .width_divisor = 2,
1559 .height_divisor = 1,
1560 .format = DRM_FORMAT_ARGB8888,
1561 .plane_index = 0
1562 }}
1563 }, {
1564 .format = DRM_FORMAT_NV12,
1565 .input_planes = 2,
1566 .output_planes = 2,
1567 .texture_type = EGL_TEXTURE_Y_UV_WL,
1568 {{
1569 .width_divisor = 1,
1570 .height_divisor = 1,
1571 .format = DRM_FORMAT_R8,
1572 .plane_index = 0
1573 }, {
1574 .width_divisor = 2,
1575 .height_divisor = 2,
1576 .format = DRM_FORMAT_GR88,
1577 .plane_index = 1
1578 }}
1579 }, {
1580 .format = DRM_FORMAT_YUV420,
1581 .input_planes = 3,
1582 .output_planes = 3,
1583 .texture_type = EGL_TEXTURE_Y_U_V_WL,
1584 {{
1585 .width_divisor = 1,
1586 .height_divisor = 1,
1587 .format = DRM_FORMAT_R8,
1588 .plane_index = 0
1589 }, {
1590 .width_divisor = 2,
1591 .height_divisor = 2,
1592 .format = DRM_FORMAT_R8,
1593 .plane_index = 1
1594 }, {
1595 .width_divisor = 2,
1596 .height_divisor = 2,
1597 .format = DRM_FORMAT_R8,
1598 .plane_index = 2
1599 }}
1600 }
1601};
1602
1603static struct egl_image *
1604import_dmabuf_single_plane(struct gl_renderer *gr,
1605 const struct dmabuf_attributes *attributes,
1606 struct yuv_plane_descriptor *descriptor)
1607{
1608 struct dmabuf_attributes plane;
1609 struct egl_image *image;
1610 char fmt[4];
1611
1612 plane.width = attributes->width / descriptor->width_divisor;
1613 plane.height = attributes->height / descriptor->height_divisor;
1614 plane.format = descriptor->format;
1615 plane.n_planes = 1;
1616 plane.fd[0] = attributes->fd[descriptor->plane_index];
1617 plane.offset[0] = attributes->offset[descriptor->plane_index];
1618 plane.stride[0] = attributes->stride[descriptor->plane_index];
1619 plane.modifier[0] = attributes->modifier[descriptor->plane_index];
1620
1621 image = import_simple_dmabuf(gr, &plane);
1622 if (!image) {
1623 weston_log("Failed to import plane %d as %.4s\n",
1624 descriptor->plane_index,
1625 dump_format(descriptor->format, fmt));
1626 return NULL;
1627 }
1628
1629 return image;
1630}
1631
1632static bool
1633import_yuv_dmabuf(struct gl_renderer *gr,
1634 struct dmabuf_image *image)
1635{
1636 unsigned i;
1637 int j;
1638 int ret;
1639 struct yuv_format_descriptor *format = NULL;
1640 struct dmabuf_attributes *attributes = &image->dmabuf->attributes;
1641 char fmt[4];
1642
1643 for (i = 0; i < ARRAY_LENGTH(yuv_formats); ++i) {
1644 if (yuv_formats[i].format == attributes->format) {
1645 format = &yuv_formats[i];
1646 break;
1647 }
1648 }
1649
1650 if (!format) {
1651 weston_log("Error during import, and no known conversion for format "
1652 "%.4s in the renderer",
1653 dump_format(attributes->format, fmt));
1654 return false;
1655 }
1656
1657 if (attributes->n_planes != format->input_planes) {
1658 weston_log("%.4s dmabuf must contain %d plane%s (%d provided)",
1659 dump_format(format->format, fmt),
1660 format->input_planes,
1661 (format->input_planes > 1) ? "s" : "",
1662 attributes->n_planes);
1663 return false;
1664 }
1665
1666 for (j = 0; j < format->output_planes; ++j) {
1667 image->images[j] = import_dmabuf_single_plane(gr, attributes,
1668 &format->plane[j]);
1669 if (!image->images[j]) {
1670 while (j) {
1671 ret = egl_image_unref(image->images[--j]);
1672 assert(ret == 0);
1673 }
1674 return false;
1675 }
1676 }
1677
1678 image->num_images = format->output_planes;
1679
1680 switch (format->texture_type) {
1681 case EGL_TEXTURE_Y_XUXV_WL:
1682 image->shader = &gr->texture_shader_y_xuxv;
1683 break;
1684 case EGL_TEXTURE_Y_UV_WL:
1685 image->shader = &gr->texture_shader_y_uv;
1686 break;
1687 case EGL_TEXTURE_Y_U_V_WL:
1688 image->shader = &gr->texture_shader_y_u_v;
1689 break;
1690 default:
1691 assert(false);
1692 }
1693
1694 return true;
1695}
1696
1697static GLenum
1698choose_texture_target(struct dmabuf_attributes *attributes)
1699{
1700 if (attributes->n_planes > 1)
1701 return GL_TEXTURE_EXTERNAL_OES;
1702
1703 switch (attributes->format & ~DRM_FORMAT_BIG_ENDIAN) {
1704 case DRM_FORMAT_YUYV:
1705 case DRM_FORMAT_YVYU:
1706 case DRM_FORMAT_UYVY:
1707 case DRM_FORMAT_VYUY:
1708 case DRM_FORMAT_AYUV:
1709 return GL_TEXTURE_EXTERNAL_OES;
1710 default:
1711 return GL_TEXTURE_2D;
1712 }
1713}
1714
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001715static struct dmabuf_image *
1716import_dmabuf(struct gl_renderer *gr,
1717 struct linux_dmabuf_buffer *dmabuf)
1718{
1719 struct egl_image *egl_image;
1720 struct dmabuf_image *image;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001721
1722 image = dmabuf_image_create();
Pekka Paalanena3525802014-06-12 16:49:29 +03001723 image->dmabuf = dmabuf;
Emmanuel Gil Peyrotbc35fda2016-01-11 19:04:35 +00001724
1725 egl_image = import_simple_dmabuf(gr, &dmabuf->attributes);
1726 if (egl_image) {
1727 image->num_images = 1;
1728 image->images[0] = egl_image;
1729 image->import_type = IMPORT_TYPE_DIRECT;
1730 image->target = choose_texture_target(&dmabuf->attributes);
1731
1732 switch (image->target) {
1733 case GL_TEXTURE_2D:
1734 image->shader = &gr->texture_shader_rgba;
1735 break;
1736 default:
1737 image->shader = &gr->texture_shader_egl_external;
1738 }
1739 } else {
1740 if (!import_yuv_dmabuf(gr, image)) {
1741 dmabuf_image_destroy(image);
1742 return NULL;
1743 }
1744 image->import_type = IMPORT_TYPE_GL_CONVERSION;
1745 image->target = GL_TEXTURE_2D;
1746 }
Pekka Paalanena3525802014-06-12 16:49:29 +03001747
1748 return image;
1749}
1750
1751static bool
1752gl_renderer_import_dmabuf(struct weston_compositor *ec,
1753 struct linux_dmabuf_buffer *dmabuf)
1754{
1755 struct gl_renderer *gr = get_renderer(ec);
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001756 struct dmabuf_image *image;
Pekka Paalanena3525802014-06-12 16:49:29 +03001757 int i;
1758
1759 assert(gr->has_dmabuf_import);
1760
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +00001761 for (i = 0; i < dmabuf->attributes.n_planes; i++) {
Pekka Paalanena3525802014-06-12 16:49:29 +03001762 /* EGL import does not have modifiers */
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +00001763 if (dmabuf->attributes.modifier[i] != 0)
Pekka Paalanena3525802014-06-12 16:49:29 +03001764 return false;
1765 }
1766
1767 /* reject all flags we do not recognize or handle */
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +00001768 if (dmabuf->attributes.flags & ~ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT)
Pekka Paalanena3525802014-06-12 16:49:29 +03001769 return false;
1770
1771 image = import_dmabuf(gr, dmabuf);
1772 if (!image)
1773 return false;
1774
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001775 wl_list_insert(&gr->dmabuf_images, &image->link);
1776 linux_dmabuf_buffer_set_user_data(dmabuf, image,
1777 gl_renderer_destroy_dmabuf);
Pekka Paalanena3525802014-06-12 16:49:29 +03001778
1779 return true;
1780}
1781
Emmanuel Gil Peyrotbc35fda2016-01-11 19:04:35 +00001782static bool
1783import_known_dmabuf(struct gl_renderer *gr,
1784 struct dmabuf_image *image)
Pekka Paalanena3525802014-06-12 16:49:29 +03001785{
Emmanuel Gil Peyrotbc35fda2016-01-11 19:04:35 +00001786 switch (image->import_type) {
1787 case IMPORT_TYPE_DIRECT:
1788 image->images[0] = import_simple_dmabuf(gr, &image->dmabuf->attributes);
1789 if (!image->images[0])
1790 return false;
1791 break;
Pekka Paalanena3525802014-06-12 16:49:29 +03001792
Emmanuel Gil Peyrotbc35fda2016-01-11 19:04:35 +00001793 case IMPORT_TYPE_GL_CONVERSION:
1794 if (!import_yuv_dmabuf(gr, image))
1795 return false;
1796 break;
1797
Pekka Paalanena3525802014-06-12 16:49:29 +03001798 default:
Emmanuel Gil Peyrotbc35fda2016-01-11 19:04:35 +00001799 weston_log("Invalid import type for dmabuf\n");
1800 return false;
Pekka Paalanena3525802014-06-12 16:49:29 +03001801 }
Emmanuel Gil Peyrotbc35fda2016-01-11 19:04:35 +00001802
1803 return true;
Pekka Paalanena3525802014-06-12 16:49:29 +03001804}
1805
1806static void
1807gl_renderer_attach_dmabuf(struct weston_surface *surface,
1808 struct weston_buffer *buffer,
1809 struct linux_dmabuf_buffer *dmabuf)
1810{
1811 struct gl_renderer *gr = get_renderer(surface->compositor);
1812 struct gl_surface_state *gs = get_surface_state(surface);
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001813 struct dmabuf_image *image;
Pekka Paalanena3525802014-06-12 16:49:29 +03001814 int i;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001815 int ret;
Pekka Paalanena3525802014-06-12 16:49:29 +03001816
1817 if (!gr->has_dmabuf_import) {
1818 linux_dmabuf_buffer_send_server_error(dmabuf,
1819 "EGL dmabuf import not supported");
1820 return;
1821 }
1822
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +00001823 buffer->width = dmabuf->attributes.width;
1824 buffer->height = dmabuf->attributes.height;
Pekka Paalanena3525802014-06-12 16:49:29 +03001825 buffer->y_inverted =
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +00001826 !!(dmabuf->attributes.flags & ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT);
Pekka Paalanena3525802014-06-12 16:49:29 +03001827
1828 for (i = 0; i < gs->num_images; i++)
1829 egl_image_unref(gs->images[i]);
1830 gs->num_images = 0;
1831
Pekka Paalanena3525802014-06-12 16:49:29 +03001832 /*
1833 * We try to always hold an imported EGLImage from the dmabuf
1834 * to prevent the client from preventing re-imports. But, we also
1835 * need to re-import every time the contents may change because
1836 * GL driver's caching may need flushing.
1837 *
1838 * Here we release the cache reference which has to be final.
1839 */
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001840 image = linux_dmabuf_buffer_get_user_data(dmabuf);
Pekka Paalanena3525802014-06-12 16:49:29 +03001841
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001842 /* The dmabuf_image should have been created during the import */
1843 assert(image != NULL);
1844
1845 for (i = 0; i < image->num_images; ++i) {
1846 ret = egl_image_unref(image->images[i]);
Pekka Paalanena3525802014-06-12 16:49:29 +03001847 assert(ret == 0);
1848 }
1849
Emmanuel Gil Peyrotbc35fda2016-01-11 19:04:35 +00001850 if (!import_known_dmabuf(gr, image)) {
1851 linux_dmabuf_buffer_send_server_error(dmabuf, "EGL dmabuf import failed");
1852 return;
Pekka Paalanena3525802014-06-12 16:49:29 +03001853 }
Pekka Paalanena3525802014-06-12 16:49:29 +03001854
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001855 gs->num_images = image->num_images;
1856 for (i = 0; i < gs->num_images; ++i)
1857 gs->images[i] = egl_image_ref(image->images[i]);
Pekka Paalanena3525802014-06-12 16:49:29 +03001858
Emmanuel Gil Peyrotbc35fda2016-01-11 19:04:35 +00001859 gs->target = image->target;
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00001860 ensure_textures(gs, gs->num_images);
1861 for (i = 0; i < gs->num_images; ++i) {
1862 glActiveTexture(GL_TEXTURE0 + i);
1863 glBindTexture(gs->target, gs->textures[i]);
1864 gr->image_target_texture_2d(gs->target, gs->images[i]->image);
1865 }
Pekka Paalanena3525802014-06-12 16:49:29 +03001866
Emmanuel Gil Peyrotbc35fda2016-01-11 19:04:35 +00001867 gs->shader = image->shader;
Pekka Paalanena3525802014-06-12 16:49:29 +03001868 gs->pitch = buffer->width;
1869 gs->height = buffer->height;
1870 gs->buffer_type = BUFFER_TYPE_EGL;
1871 gs->y_inverted = buffer->y_inverted;
1872}
1873
1874static void
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001875gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001876{
1877 struct weston_compositor *ec = es->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001878 struct gl_renderer *gr = get_renderer(ec);
1879 struct gl_surface_state *gs = get_surface_state(es);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001880 struct wl_shm_buffer *shm_buffer;
Pekka Paalanena3525802014-06-12 16:49:29 +03001881 struct linux_dmabuf_buffer *dmabuf;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001882 EGLint format;
1883 int i;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001884
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001885 weston_buffer_reference(&gs->buffer_ref, buffer);
1886
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001887 if (!buffer) {
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001888 for (i = 0; i < gs->num_images; i++) {
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +03001889 egl_image_unref(gs->images[i]);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001890 gs->images[i] = NULL;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001891 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001892 gs->num_images = 0;
1893 glDeleteTextures(gs->num_textures, gs->textures);
1894 gs->num_textures = 0;
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001895 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001896 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001897 return;
1898 }
1899
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001900 shm_buffer = wl_shm_buffer_get(buffer->resource);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001901
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001902 if (shm_buffer)
1903 gl_renderer_attach_shm(es, buffer, shm_buffer);
Kristian Høgsberg47229392013-08-07 11:59:54 -07001904 else if (gr->query_buffer(gr->egl_display, (void *) buffer->resource,
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001905 EGL_TEXTURE_FORMAT, &format))
1906 gl_renderer_attach_egl(es, buffer, format);
Pekka Paalanena3525802014-06-12 16:49:29 +03001907 else if ((dmabuf = linux_dmabuf_buffer_get(buffer->resource)))
1908 gl_renderer_attach_dmabuf(es, buffer, dmabuf);
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001909 else {
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001910 weston_log("unhandled buffer type!\n");
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001911 weston_buffer_reference(&gs->buffer_ref, NULL);
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001912 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001913 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001914 }
1915}
1916
Kristian Høgsberg42263852012-09-06 21:59:29 -04001917static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001918gl_renderer_surface_set_color(struct weston_surface *surface,
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001919 float red, float green, float blue, float alpha)
1920{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001921 struct gl_surface_state *gs = get_surface_state(surface);
1922 struct gl_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001923
1924 gs->color[0] = red;
1925 gs->color[1] = green;
1926 gs->color[2] = blue;
1927 gs->color[3] = alpha;
Pekka Paalanenaeb917e2015-02-09 13:56:56 +02001928 gs->buffer_type = BUFFER_TYPE_SOLID;
1929 gs->pitch = 1;
1930 gs->height = 1;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001931
John Kåre Alsaker40684142012-11-13 19:10:25 +01001932 gs->shader = &gr->solid_shader;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001933}
1934
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001935static void
Pekka Paalaneneb35cbe2015-02-09 13:37:27 +02001936gl_renderer_surface_get_content_size(struct weston_surface *surface,
1937 int *width, int *height)
1938{
1939 struct gl_surface_state *gs = get_surface_state(surface);
1940
1941 if (gs->buffer_type == BUFFER_TYPE_NULL) {
1942 *width = 0;
1943 *height = 0;
1944 } else {
1945 *width = gs->pitch;
1946 *height = gs->height;
1947 }
1948}
1949
1950static uint32_t
1951pack_color(pixman_format_code_t format, float *c)
1952{
1953 uint8_t r = round(c[0] * 255.0f);
1954 uint8_t g = round(c[1] * 255.0f);
1955 uint8_t b = round(c[2] * 255.0f);
1956 uint8_t a = round(c[3] * 255.0f);
1957
1958 switch (format) {
1959 case PIXMAN_a8b8g8r8:
1960 return (a << 24) | (b << 16) | (g << 8) | r;
1961 default:
1962 assert(0);
1963 return 0;
1964 }
1965}
1966
1967static int
1968gl_renderer_surface_copy_content(struct weston_surface *surface,
1969 void *target, size_t size,
1970 int src_x, int src_y,
1971 int width, int height)
1972{
1973 static const GLfloat verts[4 * 2] = {
1974 0.0f, 0.0f,
1975 1.0f, 0.0f,
1976 1.0f, 1.0f,
1977 0.0f, 1.0f
1978 };
1979 static const GLfloat projmat_normal[16] = { /* transpose */
1980 2.0f, 0.0f, 0.0f, 0.0f,
1981 0.0f, 2.0f, 0.0f, 0.0f,
1982 0.0f, 0.0f, 1.0f, 0.0f,
1983 -1.0f, -1.0f, 0.0f, 1.0f
1984 };
1985 static const GLfloat projmat_yinvert[16] = { /* transpose */
1986 2.0f, 0.0f, 0.0f, 0.0f,
1987 0.0f, -2.0f, 0.0f, 0.0f,
1988 0.0f, 0.0f, 1.0f, 0.0f,
1989 -1.0f, 1.0f, 0.0f, 1.0f
1990 };
1991 const pixman_format_code_t format = PIXMAN_a8b8g8r8;
1992 const size_t bytespp = 4; /* PIXMAN_a8b8g8r8 */
1993 const GLenum gl_format = GL_RGBA; /* PIXMAN_a8b8g8r8 little-endian */
1994 struct gl_renderer *gr = get_renderer(surface->compositor);
1995 struct gl_surface_state *gs = get_surface_state(surface);
1996 int cw, ch;
1997 GLuint fbo;
1998 GLuint tex;
1999 GLenum status;
2000 const GLfloat *proj;
2001 int i;
2002
2003 gl_renderer_surface_get_content_size(surface, &cw, &ch);
2004
2005 switch (gs->buffer_type) {
2006 case BUFFER_TYPE_NULL:
2007 return -1;
2008 case BUFFER_TYPE_SOLID:
2009 *(uint32_t *)target = pack_color(format, gs->color);
2010 return 0;
2011 case BUFFER_TYPE_SHM:
2012 gl_renderer_flush_damage(surface);
2013 /* fall through */
2014 case BUFFER_TYPE_EGL:
2015 break;
2016 }
2017
2018 glGenTextures(1, &tex);
2019 glBindTexture(GL_TEXTURE_2D, tex);
2020 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cw, ch,
2021 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2022 glBindTexture(GL_TEXTURE_2D, 0);
2023
2024 glGenFramebuffers(1, &fbo);
2025 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2026 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2027 GL_TEXTURE_2D, tex, 0);
2028
2029 status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
2030 if (status != GL_FRAMEBUFFER_COMPLETE) {
2031 weston_log("%s: fbo error: %#x\n", __func__, status);
2032 glDeleteFramebuffers(1, &fbo);
2033 glDeleteTextures(1, &tex);
2034 return -1;
2035 }
2036
2037 glViewport(0, 0, cw, ch);
2038 glDisable(GL_BLEND);
2039 use_shader(gr, gs->shader);
2040 if (gs->y_inverted)
2041 proj = projmat_normal;
2042 else
2043 proj = projmat_yinvert;
2044
2045 glUniformMatrix4fv(gs->shader->proj_uniform, 1, GL_FALSE, proj);
2046 glUniform1f(gs->shader->alpha_uniform, 1.0f);
2047
2048 for (i = 0; i < gs->num_textures; i++) {
2049 glUniform1i(gs->shader->tex_uniforms[i], i);
2050
2051 glActiveTexture(GL_TEXTURE0 + i);
2052 glBindTexture(gs->target, gs->textures[i]);
2053 glTexParameteri(gs->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2054 glTexParameteri(gs->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2055 }
2056
2057 /* position: */
2058 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
2059 glEnableVertexAttribArray(0);
2060
2061 /* texcoord: */
2062 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, verts);
2063 glEnableVertexAttribArray(1);
2064
2065 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
2066
2067 glDisableVertexAttribArray(1);
2068 glDisableVertexAttribArray(0);
2069
2070 glPixelStorei(GL_PACK_ALIGNMENT, bytespp);
2071 glReadPixels(src_x, src_y, width, height, gl_format,
2072 GL_UNSIGNED_BYTE, target);
2073
2074 glDeleteFramebuffers(1, &fbo);
2075 glDeleteTextures(1, &tex);
2076
2077 return 0;
2078}
2079
2080static void
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03002081surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr)
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03002082{
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03002083 int i;
2084
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03002085 wl_list_remove(&gs->surface_destroy_listener.link);
2086 wl_list_remove(&gs->renderer_destroy_listener.link);
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03002087
2088 gs->surface->renderer_state = NULL;
2089
2090 glDeleteTextures(gs->num_textures, gs->textures);
2091
2092 for (i = 0; i < gs->num_images; i++)
Louis-Francis Ratté-Boulianne534defd2015-06-08 16:37:05 +03002093 egl_image_unref(gs->images[i]);
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03002094
2095 weston_buffer_reference(&gs->buffer_ref, NULL);
2096 pixman_region32_fini(&gs->texture_damage);
2097 free(gs);
2098}
2099
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03002100static void
2101surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
2102{
2103 struct gl_surface_state *gs;
2104 struct gl_renderer *gr;
2105
2106 gs = container_of(listener, struct gl_surface_state,
2107 surface_destroy_listener);
2108
2109 gr = get_renderer(gs->surface->compositor);
2110
2111 surface_state_destroy(gs, gr);
2112}
2113
2114static void
2115surface_state_handle_renderer_destroy(struct wl_listener *listener, void *data)
2116{
2117 struct gl_surface_state *gs;
2118 struct gl_renderer *gr;
2119
2120 gr = data;
2121
2122 gs = container_of(listener, struct gl_surface_state,
2123 renderer_destroy_listener);
2124
2125 surface_state_destroy(gs, gr);
2126}
2127
John Kåre Alsaker878f4492012-11-13 19:10:23 +01002128static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002129gl_renderer_create_surface(struct weston_surface *surface)
John Kåre Alsaker878f4492012-11-13 19:10:23 +01002130{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002131 struct gl_surface_state *gs;
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03002132 struct gl_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01002133
Bryce Harringtonde16d892014-11-20 22:21:57 -08002134 gs = zalloc(sizeof *gs);
2135 if (gs == NULL)
John Kåre Alsaker878f4492012-11-13 19:10:23 +01002136 return -1;
2137
Pekka Paalanen68033ac2012-12-04 15:58:15 +02002138 /* A buffer is never attached to solid color surfaces, yet
2139 * they still go through texcoord computations. Do not divide
2140 * by zero there.
2141 */
2142 gs->pitch = 1;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04002143 gs->y_inverted = 1;
Pekka Paalanen68033ac2012-12-04 15:58:15 +02002144
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03002145 gs->surface = surface;
2146
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02002147 pixman_region32_init(&gs->texture_damage);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01002148 surface->renderer_state = gs;
2149
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03002150 gs->surface_destroy_listener.notify =
2151 surface_state_handle_surface_destroy;
2152 wl_signal_add(&surface->destroy_signal,
2153 &gs->surface_destroy_listener);
2154
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03002155 gs->renderer_destroy_listener.notify =
2156 surface_state_handle_renderer_destroy;
2157 wl_signal_add(&gr->destroy_signal,
2158 &gs->renderer_destroy_listener);
2159
Ander Conselvan de Oliveira895b1fd2013-11-19 15:22:05 +02002160 if (surface->buffer_ref.buffer) {
2161 gl_renderer_attach(surface, surface->buffer_ref.buffer);
2162 gl_renderer_flush_damage(surface);
2163 }
2164
John Kåre Alsaker878f4492012-11-13 19:10:23 +01002165 return 0;
2166}
2167
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002168static const char vertex_shader[] =
2169 "uniform mat4 proj;\n"
2170 "attribute vec2 position;\n"
2171 "attribute vec2 texcoord;\n"
2172 "varying vec2 v_texcoord;\n"
2173 "void main()\n"
2174 "{\n"
2175 " gl_Position = proj * vec4(position, 0.0, 1.0);\n"
2176 " v_texcoord = texcoord;\n"
2177 "}\n";
2178
2179/* Declare common fragment shader uniforms */
2180#define FRAGMENT_CONVERT_YUV \
2181 " y *= alpha;\n" \
2182 " u *= alpha;\n" \
2183 " v *= alpha;\n" \
2184 " gl_FragColor.r = y + 1.59602678 * v;\n" \
2185 " gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n" \
2186 " gl_FragColor.b = y + 2.01723214 * u;\n" \
2187 " gl_FragColor.a = alpha;\n"
2188
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002189static const char fragment_debug[] =
2190 " gl_FragColor = vec4(0.0, 0.3, 0.0, 0.2) + gl_FragColor * 0.8;\n";
2191
2192static const char fragment_brace[] =
2193 "}\n";
2194
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002195static const char texture_fragment_shader_rgba[] =
2196 "precision mediump float;\n"
2197 "varying vec2 v_texcoord;\n"
2198 "uniform sampler2D tex;\n"
2199 "uniform float alpha;\n"
2200 "void main()\n"
2201 "{\n"
2202 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002203 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002204
2205static const char texture_fragment_shader_rgbx[] =
2206 "precision mediump float;\n"
2207 "varying vec2 v_texcoord;\n"
2208 "uniform sampler2D tex;\n"
2209 "uniform float alpha;\n"
2210 "void main()\n"
2211 "{\n"
2212 " gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb\n;"
2213 " gl_FragColor.a = alpha;\n"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002214 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002215
2216static const char texture_fragment_shader_egl_external[] =
2217 "#extension GL_OES_EGL_image_external : require\n"
2218 "precision mediump float;\n"
2219 "varying vec2 v_texcoord;\n"
2220 "uniform samplerExternalOES tex;\n"
2221 "uniform float alpha;\n"
2222 "void main()\n"
2223 "{\n"
2224 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002225 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002226
2227static const char texture_fragment_shader_y_uv[] =
2228 "precision mediump float;\n"
2229 "uniform sampler2D tex;\n"
2230 "uniform sampler2D tex1;\n"
2231 "varying vec2 v_texcoord;\n"
2232 "uniform float alpha;\n"
2233 "void main() {\n"
2234 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
2235 " float u = texture2D(tex1, v_texcoord).r - 0.5;\n"
2236 " float v = texture2D(tex1, v_texcoord).g - 0.5;\n"
2237 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002238 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002239
2240static const char texture_fragment_shader_y_u_v[] =
2241 "precision mediump float;\n"
2242 "uniform sampler2D tex;\n"
2243 "uniform sampler2D tex1;\n"
2244 "uniform sampler2D tex2;\n"
2245 "varying vec2 v_texcoord;\n"
2246 "uniform float alpha;\n"
2247 "void main() {\n"
2248 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
2249 " float u = texture2D(tex1, v_texcoord).x - 0.5;\n"
2250 " float v = texture2D(tex2, v_texcoord).x - 0.5;\n"
2251 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002252 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002253
2254static const char texture_fragment_shader_y_xuxv[] =
2255 "precision mediump float;\n"
2256 "uniform sampler2D tex;\n"
2257 "uniform sampler2D tex1;\n"
2258 "varying vec2 v_texcoord;\n"
2259 "uniform float alpha;\n"
2260 "void main() {\n"
2261 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
2262 " float u = texture2D(tex1, v_texcoord).g - 0.5;\n"
2263 " float v = texture2D(tex1, v_texcoord).a - 0.5;\n"
2264 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002265 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002266
2267static const char solid_fragment_shader[] =
2268 "precision mediump float;\n"
2269 "uniform vec4 color;\n"
2270 "uniform float alpha;\n"
2271 "void main()\n"
2272 "{\n"
2273 " gl_FragColor = alpha * color\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002274 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002275
2276static int
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002277compile_shader(GLenum type, int count, const char **sources)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002278{
2279 GLuint s;
2280 char msg[512];
2281 GLint status;
2282
2283 s = glCreateShader(type);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002284 glShaderSource(s, count, sources, NULL);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002285 glCompileShader(s);
2286 glGetShaderiv(s, GL_COMPILE_STATUS, &status);
2287 if (!status) {
2288 glGetShaderInfoLog(s, sizeof msg, NULL, msg);
2289 weston_log("shader info: %s\n", msg);
2290 return GL_NONE;
2291 }
2292
2293 return s;
2294}
2295
2296static int
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03002297shader_init(struct gl_shader *shader, struct gl_renderer *renderer,
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002298 const char *vertex_source, const char *fragment_source)
2299{
2300 char msg[512];
2301 GLint status;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002302 int count;
2303 const char *sources[3];
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002304
2305 shader->vertex_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002306 compile_shader(GL_VERTEX_SHADER, 1, &vertex_source);
2307
2308 if (renderer->fragment_shader_debug) {
2309 sources[0] = fragment_source;
2310 sources[1] = fragment_debug;
2311 sources[2] = fragment_brace;
2312 count = 3;
2313 } else {
2314 sources[0] = fragment_source;
2315 sources[1] = fragment_brace;
2316 count = 2;
2317 }
2318
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002319 shader->fragment_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002320 compile_shader(GL_FRAGMENT_SHADER, count, sources);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002321
2322 shader->program = glCreateProgram();
2323 glAttachShader(shader->program, shader->vertex_shader);
2324 glAttachShader(shader->program, shader->fragment_shader);
2325 glBindAttribLocation(shader->program, 0, "position");
2326 glBindAttribLocation(shader->program, 1, "texcoord");
2327
2328 glLinkProgram(shader->program);
2329 glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
2330 if (!status) {
2331 glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
2332 weston_log("link info: %s\n", msg);
2333 return -1;
2334 }
2335
2336 shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
2337 shader->tex_uniforms[0] = glGetUniformLocation(shader->program, "tex");
2338 shader->tex_uniforms[1] = glGetUniformLocation(shader->program, "tex1");
2339 shader->tex_uniforms[2] = glGetUniformLocation(shader->program, "tex2");
2340 shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
2341 shader->color_uniform = glGetUniformLocation(shader->program, "color");
2342
2343 return 0;
2344}
2345
2346static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002347shader_release(struct gl_shader *shader)
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002348{
2349 glDeleteShader(shader->vertex_shader);
2350 glDeleteShader(shader->fragment_shader);
2351 glDeleteProgram(shader->program);
2352
2353 shader->vertex_shader = 0;
2354 shader->fragment_shader = 0;
2355 shader->program = 0;
2356}
2357
2358static void
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04002359log_extensions(const char *name, const char *extensions)
2360{
2361 const char *p, *end;
2362 int l;
2363 int len;
2364
2365 l = weston_log("%s:", name);
2366 p = extensions;
2367 while (*p) {
2368 end = strchrnul(p, ' ');
2369 len = end - p;
2370 if (l + len > 78)
2371 l = weston_log_continue("\n" STAMP_SPACE "%.*s",
2372 len, p);
2373 else
2374 l += weston_log_continue(" %.*s", len, p);
2375 for (p = end; isspace(*p); p++)
2376 ;
2377 }
2378 weston_log_continue("\n");
2379}
2380
2381static void
2382log_egl_gl_info(EGLDisplay egldpy)
2383{
2384 const char *str;
2385
2386 str = eglQueryString(egldpy, EGL_VERSION);
2387 weston_log("EGL version: %s\n", str ? str : "(null)");
2388
2389 str = eglQueryString(egldpy, EGL_VENDOR);
2390 weston_log("EGL vendor: %s\n", str ? str : "(null)");
2391
2392 str = eglQueryString(egldpy, EGL_CLIENT_APIS);
2393 weston_log("EGL client APIs: %s\n", str ? str : "(null)");
2394
2395 str = eglQueryString(egldpy, EGL_EXTENSIONS);
2396 log_extensions("EGL extensions", str ? str : "(null)");
2397
2398 str = (char *)glGetString(GL_VERSION);
2399 weston_log("GL version: %s\n", str ? str : "(null)");
2400
2401 str = (char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
2402 weston_log("GLSL version: %s\n", str ? str : "(null)");
2403
2404 str = (char *)glGetString(GL_VENDOR);
2405 weston_log("GL vendor: %s\n", str ? str : "(null)");
2406
2407 str = (char *)glGetString(GL_RENDERER);
2408 weston_log("GL renderer: %s\n", str ? str : "(null)");
2409
2410 str = (char *)glGetString(GL_EXTENSIONS);
2411 log_extensions("GL extensions", str ? str : "(null)");
2412}
2413
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03002414static void
2415log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
2416{
2417 EGLint r, g, b, a;
2418
2419 weston_log("Chosen EGL config details:\n");
2420
2421 weston_log_continue(STAMP_SPACE "RGBA bits");
2422 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_RED_SIZE, &r) &&
2423 eglGetConfigAttrib(egldpy, eglconfig, EGL_GREEN_SIZE, &g) &&
2424 eglGetConfigAttrib(egldpy, eglconfig, EGL_BLUE_SIZE, &b) &&
2425 eglGetConfigAttrib(egldpy, eglconfig, EGL_ALPHA_SIZE, &a))
2426 weston_log_continue(": %d %d %d %d\n", r, g, b, a);
2427 else
2428 weston_log_continue(" unknown\n");
2429
2430 weston_log_continue(STAMP_SPACE "swap interval range");
2431 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_MIN_SWAP_INTERVAL, &a) &&
2432 eglGetConfigAttrib(egldpy, eglconfig, EGL_MAX_SWAP_INTERVAL, &b))
2433 weston_log_continue(": %d - %d\n", a, b);
2434 else
2435 weston_log_continue(" unknown\n");
2436}
2437
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002438static int
Derek Foremane76f1852015-05-15 12:12:39 -05002439match_config_to_visual(EGLDisplay egl_display,
2440 EGLint visual_id,
2441 EGLConfig *configs,
2442 int count)
2443{
2444 int i;
2445
2446 for (i = 0; i < count; ++i) {
2447 EGLint id;
2448
2449 if (!eglGetConfigAttrib(egl_display,
2450 configs[i], EGL_NATIVE_VISUAL_ID,
2451 &id))
2452 continue;
2453
2454 if (id == visual_id)
2455 return i;
2456 }
2457
Derek Foremane76f1852015-05-15 12:12:39 -05002458 return -1;
2459}
2460
2461static int
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002462egl_choose_config(struct gl_renderer *gr, const EGLint *attribs,
Derek Foremane76f1852015-05-15 12:12:39 -05002463 const EGLint *visual_id, const int n_ids,
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002464 EGLConfig *config_out)
2465{
2466 EGLint count = 0;
2467 EGLint matched = 0;
2468 EGLConfig *configs;
Derek Foremane76f1852015-05-15 12:12:39 -05002469 int i, config_index = -1;
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002470
Derek Foremana7e19912015-05-20 14:57:58 -05002471 if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1) {
2472 weston_log("No EGL configs to choose from.\n");
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002473 return -1;
Derek Foremana7e19912015-05-20 14:57:58 -05002474 }
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002475 configs = calloc(count, sizeof *configs);
2476 if (!configs)
2477 return -1;
2478
2479 if (!eglChooseConfig(gr->egl_display, attribs, configs,
Derek Foremana7e19912015-05-20 14:57:58 -05002480 count, &matched) || !matched) {
2481 weston_log("No EGL configs with appropriate attributes.\n");
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002482 goto out;
Derek Foremana7e19912015-05-20 14:57:58 -05002483 }
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002484
Derek Foremane76f1852015-05-15 12:12:39 -05002485 if (!visual_id)
2486 config_index = 0;
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002487
Derek Foremane76f1852015-05-15 12:12:39 -05002488 for (i = 0; config_index == -1 && i < n_ids; i++)
2489 config_index = match_config_to_visual(gr->egl_display,
2490 visual_id[i],
2491 configs,
2492 matched);
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002493
Derek Foremane76f1852015-05-15 12:12:39 -05002494 if (config_index != -1)
2495 *config_out = configs[config_index];
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002496
2497out:
2498 free(configs);
Derek Foremane76f1852015-05-15 12:12:39 -05002499 if (config_index == -1)
2500 return -1;
2501
Derek Foremana7e19912015-05-20 14:57:58 -05002502 if (i > 1)
2503 weston_log("Unable to use first choice EGL config with id"
2504 " 0x%x, succeeded with alternate id 0x%x.\n",
2505 visual_id[0], visual_id[i - 1]);
Derek Foremane76f1852015-05-15 12:12:39 -05002506 return 0;
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002507}
2508
John Kåre Alsaker44154502012-11-13 19:10:20 +01002509static void
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05002510gl_renderer_output_set_border(struct weston_output *output,
2511 enum gl_renderer_border_side side,
2512 int32_t width, int32_t height,
2513 int32_t tex_width, unsigned char *data)
2514{
2515 struct gl_output_state *go = get_output_state(output);
2516
Jason Ekstrande5512d42014-02-04 21:36:38 -06002517 if (go->borders[side].width != width ||
2518 go->borders[side].height != height)
2519 /* In this case, we have to blow everything and do a full
2520 * repaint. */
2521 go->border_status |= BORDER_SIZE_CHANGED | BORDER_ALL_DIRTY;
2522
2523 if (data == NULL) {
2524 width = 0;
2525 height = 0;
2526 }
2527
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05002528 go->borders[side].width = width;
2529 go->borders[side].height = height;
2530 go->borders[side].tex_width = tex_width;
2531 go->borders[side].data = data;
Jason Ekstrande5512d42014-02-04 21:36:38 -06002532 go->border_status |= 1 << side;
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05002533}
2534
John Kåre Alsaker94659272012-11-13 19:10:18 +01002535static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002536gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01002537
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002538static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002539gl_renderer_output_create(struct weston_output *output,
Jonny Lamb671148f2015-03-20 15:26:52 +01002540 EGLNativeWindowType window_for_legacy,
2541 void *window_for_platform,
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002542 const EGLint *attribs,
Derek Foremane76f1852015-05-15 12:12:39 -05002543 const EGLint *visual_id,
2544 int n_ids)
John Kåre Alsaker94659272012-11-13 19:10:18 +01002545{
2546 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002547 struct gl_renderer *gr = get_renderer(ec);
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002548 struct gl_output_state *go;
2549 EGLConfig egl_config;
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02002550 int i;
John Kåre Alsaker94659272012-11-13 19:10:18 +01002551
Derek Foremane76f1852015-05-15 12:12:39 -05002552 if (egl_choose_config(gr, attribs, visual_id,
2553 n_ids, &egl_config) == -1) {
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002554 weston_log("failed to choose EGL config for output\n");
2555 return -1;
2556 }
2557
2558 if (egl_config != gr->egl_config &&
2559 !gr->has_configless_context) {
2560 weston_log("attempted to use a different EGL config for an "
2561 "output but EGL_MESA_configless_context is not "
2562 "supported\n");
2563 return -1;
2564 }
2565
Bryce Harringtonde16d892014-11-20 22:21:57 -08002566 go = zalloc(sizeof *go);
2567 if (go == NULL)
John Kåre Alsaker94659272012-11-13 19:10:18 +01002568 return -1;
2569
Jonny Lamb671148f2015-03-20 15:26:52 +01002570 if (gr->create_platform_window) {
2571 go->egl_surface =
2572 gr->create_platform_window(gr->egl_display,
2573 egl_config,
2574 window_for_platform,
2575 NULL);
Jonny Lambf1ec5062015-03-24 13:12:05 +01002576 } else {
Jonny Lamb671148f2015-03-20 15:26:52 +01002577 go->egl_surface =
2578 eglCreateWindowSurface(gr->egl_display,
2579 egl_config,
2580 window_for_legacy, NULL);
Jonny Lambf1ec5062015-03-24 13:12:05 +01002581 }
John Kåre Alsaker94659272012-11-13 19:10:18 +01002582
2583 if (go->egl_surface == EGL_NO_SURFACE) {
2584 weston_log("failed to create egl surface\n");
2585 free(go);
2586 return -1;
2587 }
2588
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02002589 for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02002590 pixman_region32_init(&go->buffer_damage[i]);
2591
John Kåre Alsaker94659272012-11-13 19:10:18 +01002592 output->renderer_state = go;
2593
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002594 log_egl_config_info(gr->egl_display, egl_config);
2595
John Kåre Alsaker94659272012-11-13 19:10:18 +01002596 return 0;
2597}
2598
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002599static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002600gl_renderer_output_destroy(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01002601{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002602 struct gl_renderer *gr = get_renderer(output->compositor);
2603 struct gl_output_state *go = get_output_state(output);
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02002604 int i;
2605
2606 for (i = 0; i < 2; i++)
2607 pixman_region32_fini(&go->buffer_damage[i]);
John Kåre Alsaker94659272012-11-13 19:10:18 +01002608
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002609 eglDestroySurface(gr->egl_display, go->egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01002610
2611 free(go);
2612}
2613
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002614static EGLSurface
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002615gl_renderer_output_surface(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01002616{
2617 return get_output_state(output)->egl_surface;
2618}
2619
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03002620static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002621gl_renderer_destroy(struct weston_compositor *ec)
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04002622{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002623 struct gl_renderer *gr = get_renderer(ec);
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00002624 struct dmabuf_image *image, *next;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002625
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03002626 wl_signal_emit(&gr->destroy_signal, gr);
2627
John Kåre Alsaker320711d2012-11-13 19:10:27 +01002628 if (gr->has_bind_display)
2629 gr->unbind_display(gr->egl_display, ec->wl_display);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002630
2631 /* Work around crash in egl_dri2.c's dri2_make_current() - when does this apply? */
2632 eglMakeCurrent(gr->egl_display,
2633 EGL_NO_SURFACE, EGL_NO_SURFACE,
2634 EGL_NO_CONTEXT);
2635
Pekka Paalanena3525802014-06-12 16:49:29 +03002636
Emmanuel Gil Peyrotb8053502016-01-11 19:04:34 +00002637 wl_list_for_each_safe(image, next, &gr->dmabuf_images, link)
2638 dmabuf_image_destroy(image);
Pekka Paalanena3525802014-06-12 16:49:29 +03002639
Armin Krezović28d240f2016-06-23 11:59:35 +02002640 if (gr->dummy_surface != EGL_NO_SURFACE)
2641 eglDestroySurface(gr->egl_display, gr->dummy_surface);
2642
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002643 eglTerminate(gr->egl_display);
2644 eglReleaseThread();
Scott Moreau976a0502013-03-07 10:15:17 -07002645
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -04002646 wl_array_release(&gr->vertices);
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -04002647 wl_array_release(&gr->vtxcnt);
2648
Mariusz Ceiercbb91582014-02-08 20:11:24 +01002649 if (gr->fragment_binding)
2650 weston_binding_destroy(gr->fragment_binding);
2651 if (gr->fan_binding)
2652 weston_binding_destroy(gr->fan_binding);
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +03002653
Scott Moreau976a0502013-03-07 10:15:17 -07002654 free(gr);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002655}
2656
Pekka Paalanen8b69d032015-04-08 17:02:22 +03002657static void
2658renderer_setup_egl_client_extensions(struct gl_renderer *gr)
2659{
2660 const char *extensions;
2661
2662 extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
2663 if (!extensions) {
2664 weston_log("Retrieving EGL client extension string failed.\n");
2665 return;
2666 }
2667
Emil Velikovf0c3a1c2016-07-04 15:34:18 +01002668 if (weston_check_egl_extension(extensions, "EGL_EXT_platform_base"))
Pekka Paalanen8b69d032015-04-08 17:02:22 +03002669 gr->create_platform_window =
2670 (void *) eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT");
2671 else
2672 weston_log("warning: EGL_EXT_platform_base not supported.\n");
2673}
2674
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002675static int
Neil Robertsb7f85332014-03-07 18:05:49 +00002676gl_renderer_setup_egl_extensions(struct weston_compositor *ec)
2677{
2678 struct gl_renderer *gr = get_renderer(ec);
2679 const char *extensions;
2680 EGLBoolean ret;
2681
2682 gr->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
2683 gr->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
2684 gr->bind_display =
2685 (void *) eglGetProcAddress("eglBindWaylandDisplayWL");
2686 gr->unbind_display =
2687 (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
2688 gr->query_buffer =
2689 (void *) eglGetProcAddress("eglQueryWaylandBufferWL");
2690
2691 extensions =
2692 (const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
2693 if (!extensions) {
2694 weston_log("Retrieving EGL extension string failed.\n");
2695 return -1;
2696 }
2697
Emil Velikovf0c3a1c2016-07-04 15:34:18 +01002698 if (weston_check_egl_extension(extensions, "EGL_WL_bind_wayland_display"))
Neil Robertsb7f85332014-03-07 18:05:49 +00002699 gr->has_bind_display = 1;
2700 if (gr->has_bind_display) {
2701 ret = gr->bind_display(gr->egl_display, ec->wl_display);
2702 if (!ret)
2703 gr->has_bind_display = 0;
2704 }
2705
Emil Velikovf0c3a1c2016-07-04 15:34:18 +01002706 if (weston_check_egl_extension(extensions, "EGL_EXT_buffer_age"))
Neil Robertsb7f85332014-03-07 18:05:49 +00002707 gr->has_egl_buffer_age = 1;
2708 else
2709 weston_log("warning: EGL_EXT_buffer_age not supported. "
2710 "Performance could be affected.\n");
2711
Emil Velikovf0c3a1c2016-07-04 15:34:18 +01002712 if (weston_check_egl_extension(extensions, "EGL_EXT_swap_buffers_with_damage"))
Neil Robertsb7f85332014-03-07 18:05:49 +00002713 gr->swap_buffers_with_damage =
2714 (void *) eglGetProcAddress("eglSwapBuffersWithDamageEXT");
2715 else
2716 weston_log("warning: EGL_EXT_swap_buffers_with_damage not "
2717 "supported. Performance could be affected.\n");
Neil Robertsb7f85332014-03-07 18:05:49 +00002718
Emil Velikovf0c3a1c2016-07-04 15:34:18 +01002719 if (weston_check_egl_extension(extensions, "EGL_MESA_configless_context"))
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002720 gr->has_configless_context = 1;
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002721
Emil Velikovf0c3a1c2016-07-04 15:34:18 +01002722 if (weston_check_egl_extension(extensions, "EGL_KHR_surfaceless_context"))
Armin Krezović28d240f2016-06-23 11:59:35 +02002723 gr->has_surfaceless_context = 1;
2724
Emil Velikovf0c3a1c2016-07-04 15:34:18 +01002725 if (weston_check_egl_extension(extensions, "EGL_EXT_image_dma_buf_import"))
Pekka Paalanena3525802014-06-12 16:49:29 +03002726 gr->has_dmabuf_import = 1;
Pekka Paalanena3525802014-06-12 16:49:29 +03002727
Pekka Paalanen8b69d032015-04-08 17:02:22 +03002728 renderer_setup_egl_client_extensions(gr);
2729
Neil Robertsb7f85332014-03-07 18:05:49 +00002730 return 0;
2731}
2732
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002733static const EGLint gl_renderer_opaque_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002734 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
2735 EGL_RED_SIZE, 1,
2736 EGL_GREEN_SIZE, 1,
2737 EGL_BLUE_SIZE, 1,
2738 EGL_ALPHA_SIZE, 0,
2739 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
2740 EGL_NONE
2741};
2742
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002743static const EGLint gl_renderer_alpha_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002744 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
2745 EGL_RED_SIZE, 1,
2746 EGL_GREEN_SIZE, 1,
2747 EGL_BLUE_SIZE, 1,
2748 EGL_ALPHA_SIZE, 1,
2749 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
2750 EGL_NONE
2751};
2752
Armin Krezović28d240f2016-06-23 11:59:35 +02002753
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002754/** Checks whether a platform EGL client extension is supported
2755 *
2756 * \param ec The weston compositor
2757 * \param extension_suffix The EGL client extension suffix
2758 * \return 1 if supported, 0 if using fallbacks, -1 unsupported
2759 *
2760 * This function checks whether a specific platform_* extension is supported
2761 * by EGL.
2762 *
2763 * The extension suffix should be the suffix of the platform extension (that
2764 * specifies a <platform> argument as defined in EGL_EXT_platform_base). For
2765 * example, passing "foo" will check whether either "EGL_KHR_platform_foo",
2766 * "EGL_EXT_platform_foo", or "EGL_MESA_platform_foo" is supported.
2767 *
2768 * The return value is 1:
2769 * - if the supplied EGL client extension is supported.
2770 * The return value is 0:
2771 * - if the platform_base client extension isn't supported so will
2772 * fallback to eglGetDisplay and friends.
2773 * The return value is -1:
2774 * - if the supplied EGL client extension is not supported.
2775 */
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002776static int
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002777gl_renderer_supports(struct weston_compositor *ec,
2778 const char *extension_suffix)
2779{
2780 static const char *extensions = NULL;
2781 char s[64];
2782
2783 if (!extensions) {
2784 extensions = (const char *) eglQueryString(
2785 EGL_NO_DISPLAY, EGL_EXTENSIONS);
2786
2787 if (!extensions)
2788 return 0;
2789
2790 log_extensions("EGL client extensions",
2791 extensions);
2792 }
2793
Emil Velikovf0c3a1c2016-07-04 15:34:18 +01002794 if (!weston_check_egl_extension(extensions, "EGL_EXT_platform_base"))
Pekka Paalanenf2824542015-04-08 17:02:21 +03002795 return 0;
2796
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002797 snprintf(s, sizeof s, "EGL_KHR_platform_%s", extension_suffix);
Emil Velikovf0c3a1c2016-07-04 15:34:18 +01002798 if (weston_check_egl_extension(extensions, s))
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002799 return 1;
2800
2801 snprintf(s, sizeof s, "EGL_EXT_platform_%s", extension_suffix);
Emil Velikovf0c3a1c2016-07-04 15:34:18 +01002802 if (weston_check_egl_extension(extensions, s))
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002803 return 1;
2804
2805 snprintf(s, sizeof s, "EGL_MESA_platform_%s", extension_suffix);
Emil Velikovf0c3a1c2016-07-04 15:34:18 +01002806 if (weston_check_egl_extension(extensions, s))
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002807 return 1;
2808
Pekka Paalanenf2824542015-04-08 17:02:21 +03002809 /* at this point we definitely have some platform extensions but
2810 * haven't found the supplied platform, so chances are it's
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002811 * not supported. */
2812
2813 return -1;
2814}
2815
Jonny Lamb74eed312015-03-24 13:12:04 +01002816static const char *
2817platform_to_extension(EGLenum platform)
2818{
2819 switch (platform) {
2820 case EGL_PLATFORM_GBM_KHR:
2821 return "gbm";
2822 case EGL_PLATFORM_WAYLAND_KHR:
2823 return "wayland";
2824 case EGL_PLATFORM_X11_KHR:
2825 return "x11";
2826 default:
2827 assert(0 && "bad EGL platform enum");
2828 }
2829}
2830
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002831static int
Armin Krezović28d240f2016-06-23 11:59:35 +02002832gl_renderer_create_pbuffer_surface(struct gl_renderer *gr) {
2833 EGLConfig pbuffer_config;
2834
2835 static const EGLint pbuffer_config_attribs[] = {
2836 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
2837 EGL_RED_SIZE, 1,
2838 EGL_GREEN_SIZE, 1,
2839 EGL_BLUE_SIZE, 1,
2840 EGL_ALPHA_SIZE, 0,
2841 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
2842 EGL_NONE
2843 };
2844
2845 static const EGLint pbuffer_attribs[] = {
2846 EGL_WIDTH, 10,
2847 EGL_HEIGHT, 10,
2848 EGL_NONE
2849 };
2850
2851 if (egl_choose_config(gr, pbuffer_config_attribs, NULL, 0, &pbuffer_config) < 0) {
2852 weston_log("failed to choose EGL config for PbufferSurface");
2853 return -1;
2854 }
2855
2856 gr->dummy_surface = eglCreatePbufferSurface(gr->egl_display,
2857 pbuffer_config,
2858 pbuffer_attribs);
2859
2860 if (gr->dummy_surface == EGL_NO_SURFACE) {
2861 weston_log("failed to create PbufferSurface\n");
2862 return -1;
2863 }
2864
2865 return 0;
2866}
2867
2868static int
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002869gl_renderer_create(struct weston_compositor *ec, EGLenum platform,
2870 void *native_window, const EGLint *attribs,
Derek Foremane76f1852015-05-15 12:12:39 -05002871 const EGLint *visual_id, int n_ids)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002872{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002873 struct gl_renderer *gr;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002874 EGLint major, minor;
Jonny Lamb74eed312015-03-24 13:12:04 +01002875 int supports = 0;
2876
2877 if (platform) {
2878 supports = gl_renderer_supports(
2879 ec, platform_to_extension(platform));
2880 if (supports < 0)
2881 return -1;
2882 }
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002883
Bryce Harringtonde16d892014-11-20 22:21:57 -08002884 gr = zalloc(sizeof *gr);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002885 if (gr == NULL)
2886 return -1;
2887
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002888 gr->base.read_pixels = gl_renderer_read_pixels;
2889 gr->base.repaint_output = gl_renderer_repaint_output;
2890 gr->base.flush_damage = gl_renderer_flush_damage;
2891 gr->base.attach = gl_renderer_attach;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002892 gr->base.surface_set_color = gl_renderer_surface_set_color;
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03002893 gr->base.destroy = gl_renderer_destroy;
Pekka Paalaneneb35cbe2015-02-09 13:37:27 +02002894 gr->base.surface_get_content_size =
2895 gl_renderer_surface_get_content_size;
2896 gr->base.surface_copy_content = gl_renderer_surface_copy_content;
Jonny Lamb74eed312015-03-24 13:12:04 +01002897 gr->egl_display = NULL;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002898
Jonny Lambf1ec5062015-03-24 13:12:05 +01002899 /* extension_suffix is supported */
Jonny Lamb74eed312015-03-24 13:12:04 +01002900 if (supports) {
2901 if (!get_platform_display) {
2902 get_platform_display = (void *) eglGetProcAddress(
2903 "eglGetPlatformDisplayEXT");
2904 }
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002905
Jonny Lamb74eed312015-03-24 13:12:04 +01002906 /* also wrap this in the supports check because
2907 * eglGetProcAddress can return non-NULL and still not
2908 * support the feature at runtime, so ensure the
2909 * appropriate extension checks have been done. */
2910 if (get_platform_display && platform) {
2911 gr->egl_display = get_platform_display(platform,
2912 native_window,
2913 NULL);
2914 }
2915 }
Jonny Lamb74eed312015-03-24 13:12:04 +01002916
2917 if (!gr->egl_display) {
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002918 weston_log("warning: either no EGL_EXT_platform_base "
2919 "support or specific platform support; "
2920 "falling back to eglGetDisplay.\n");
2921 gr->egl_display = eglGetDisplay(native_window);
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002922 }
Jonny Lamb70eba3f2015-03-20 15:26:50 +01002923
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002924 if (gr->egl_display == EGL_NO_DISPLAY) {
2925 weston_log("failed to create display\n");
Derek Foreman066ca0c2015-06-11 12:14:45 -05002926 goto fail;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002927 }
2928
2929 if (!eglInitialize(gr->egl_display, &major, &minor)) {
2930 weston_log("failed to initialize display\n");
Derek Foreman066ca0c2015-06-11 12:14:45 -05002931 goto fail_with_error;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002932 }
2933
Derek Foremane76f1852015-05-15 12:12:39 -05002934 if (egl_choose_config(gr, attribs, visual_id,
2935 n_ids, &gr->egl_config) < 0) {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002936 weston_log("failed to choose EGL config\n");
Dawid Gajownik1a912a92015-08-21 00:20:54 -03002937 goto fail_terminate;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002938 }
2939
2940 ec->renderer = &gr->base;
Pekka Paalanen7bb65102013-05-22 18:03:04 +03002941 ec->capabilities |= WESTON_CAP_ROTATION_ANY;
Pekka Paalanen4fc5dd02013-05-22 18:03:05 +03002942 ec->capabilities |= WESTON_CAP_CAPTURE_YFLIP;
Pekka Paalanenfa79b1d2015-02-18 09:48:59 +02002943 ec->capabilities |= WESTON_CAP_VIEW_CLIP_MASK;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002944
Neil Robertsb7f85332014-03-07 18:05:49 +00002945 if (gl_renderer_setup_egl_extensions(ec) < 0)
Derek Foreman066ca0c2015-06-11 12:14:45 -05002946 goto fail_with_error;
Neil Robertsb7f85332014-03-07 18:05:49 +00002947
Pekka Paalanena3525802014-06-12 16:49:29 +03002948 wl_list_init(&gr->dmabuf_images);
2949 if (gr->has_dmabuf_import)
2950 gr->base.import_dmabuf = gl_renderer_import_dmabuf;
2951
Armin Krezović28d240f2016-06-23 11:59:35 +02002952 if (gr->has_surfaceless_context) {
2953 weston_log("EGL_KHR_surfaceless_context available\n");
2954 gr->dummy_surface = EGL_NO_SURFACE;
2955 } else {
2956 weston_log("EGL_KHR_surfaceless_context unavailable. "
2957 "Trying PbufferSurface\n");
2958
2959 if (gl_renderer_create_pbuffer_surface(gr) < 0)
2960 goto fail_with_error;
2961 }
2962
Tomeu Vizoso12072b62013-08-06 20:05:55 +02002963 wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565);
2964
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03002965 wl_signal_init(&gr->destroy_signal);
2966
Armin Krezović28d240f2016-06-23 11:59:35 +02002967 if (gl_renderer_setup(ec, gr->dummy_surface) < 0) {
2968 if (gr->dummy_surface != EGL_NO_SURFACE)
2969 eglDestroySurface(gr->egl_display, gr->dummy_surface);
2970 goto fail_with_error;
2971 }
2972
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002973 return 0;
2974
Derek Foreman066ca0c2015-06-11 12:14:45 -05002975fail_with_error:
Pekka Paalanen326529f2012-11-27 12:25:25 +02002976 gl_renderer_print_egl_error_state();
Dawid Gajownik1a912a92015-08-21 00:20:54 -03002977fail_terminate:
2978 eglTerminate(gr->egl_display);
Derek Foreman066ca0c2015-06-11 12:14:45 -05002979fail:
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002980 free(gr);
2981 return -1;
2982}
2983
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002984static EGLDisplay
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002985gl_renderer_display(struct weston_compositor *ec)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01002986{
2987 return get_renderer(ec)->egl_display;
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04002988}
2989
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02002990static int
2991compile_shaders(struct weston_compositor *ec)
2992{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01002993 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker40684142012-11-13 19:10:25 +01002994
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03002995 gr->texture_shader_rgba.vertex_source = vertex_shader;
2996 gr->texture_shader_rgba.fragment_source = texture_fragment_shader_rgba;
2997
2998 gr->texture_shader_rgbx.vertex_source = vertex_shader;
2999 gr->texture_shader_rgbx.fragment_source = texture_fragment_shader_rgbx;
3000
3001 gr->texture_shader_egl_external.vertex_source = vertex_shader;
3002 gr->texture_shader_egl_external.fragment_source =
3003 texture_fragment_shader_egl_external;
3004
3005 gr->texture_shader_y_uv.vertex_source = vertex_shader;
3006 gr->texture_shader_y_uv.fragment_source = texture_fragment_shader_y_uv;
3007
3008 gr->texture_shader_y_u_v.vertex_source = vertex_shader;
3009 gr->texture_shader_y_u_v.fragment_source =
3010 texture_fragment_shader_y_u_v;
3011
Ander Conselvan de Oliveira41a50ea2013-11-27 17:43:51 +02003012 gr->texture_shader_y_xuxv.vertex_source = vertex_shader;
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03003013 gr->texture_shader_y_xuxv.fragment_source =
3014 texture_fragment_shader_y_xuxv;
3015
3016 gr->solid_shader.vertex_source = vertex_shader;
3017 gr->solid_shader.fragment_source = solid_fragment_shader;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02003018
3019 return 0;
3020}
3021
3022static void
Derek Foreman8ae2db52015-07-15 13:00:36 -05003023fragment_debug_binding(struct weston_keyboard *keyboard, uint32_t time,
3024 uint32_t key, void *data)
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02003025{
3026 struct weston_compositor *ec = data;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01003027 struct gl_renderer *gr = get_renderer(ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02003028 struct weston_output *output;
3029
John Kåre Alsaker40684142012-11-13 19:10:25 +01003030 gr->fragment_shader_debug ^= 1;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02003031
John Kåre Alsaker40684142012-11-13 19:10:25 +01003032 shader_release(&gr->texture_shader_rgba);
3033 shader_release(&gr->texture_shader_rgbx);
3034 shader_release(&gr->texture_shader_egl_external);
3035 shader_release(&gr->texture_shader_y_uv);
3036 shader_release(&gr->texture_shader_y_u_v);
3037 shader_release(&gr->texture_shader_y_xuxv);
3038 shader_release(&gr->solid_shader);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02003039
Ander Conselvan de Oliveira03fb4ef2012-12-03 17:08:11 +02003040 /* Force use_shader() to call glUseProgram(), since we need to use
3041 * the recompiled version of the shader. */
3042 gr->current_shader = NULL;
3043
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02003044 wl_list_for_each(output, &ec->output_list, link)
3045 weston_output_damage(output);
3046}
3047
Kristian Høgsberg8799d412013-05-07 10:50:09 -04003048static void
Derek Foreman8ae2db52015-07-15 13:00:36 -05003049fan_debug_repaint_binding(struct weston_keyboard *keyboard, uint32_t time,
3050 uint32_t key, void *data)
Kristian Høgsberg8799d412013-05-07 10:50:09 -04003051{
3052 struct weston_compositor *compositor = data;
3053 struct gl_renderer *gr = get_renderer(compositor);
3054
3055 gr->fan_debug = !gr->fan_debug;
3056 weston_compositor_damage_all(compositor);
3057}
3058
John Kåre Alsaker94659272012-11-13 19:10:18 +01003059static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01003060gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04003061{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01003062 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04003063 const char *extensions;
Neil Roberts77c1a5b2014-03-07 18:05:50 +00003064 EGLConfig context_config;
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04003065 EGLBoolean ret;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04003066
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04003067 static const EGLint context_attribs[] = {
3068 EGL_CONTEXT_CLIENT_VERSION, 2,
3069 EGL_NONE
3070 };
3071
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04003072 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
3073 weston_log("failed to bind EGL_OPENGL_ES_API\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02003074 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04003075 return -1;
3076 }
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03003077
Neil Roberts77c1a5b2014-03-07 18:05:50 +00003078 context_config = gr->egl_config;
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03003079
Neil Roberts77c1a5b2014-03-07 18:05:50 +00003080 if (gr->has_configless_context)
3081 context_config = EGL_NO_CONFIG_MESA;
Neil Roberts77c1a5b2014-03-07 18:05:50 +00003082
3083 gr->egl_context = eglCreateContext(gr->egl_display, context_config,
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04003084 EGL_NO_CONTEXT, context_attribs);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01003085 if (gr->egl_context == NULL) {
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04003086 weston_log("failed to create context\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02003087 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04003088 return -1;
3089 }
3090
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01003091 ret = eglMakeCurrent(gr->egl_display, egl_surface,
3092 egl_surface, gr->egl_context);
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04003093 if (ret == EGL_FALSE) {
3094 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02003095 gl_renderer_print_egl_error_state();
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04003096 return -1;
3097 }
3098
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01003099 log_egl_gl_info(gr->egl_display);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04003100
John Kåre Alsaker320711d2012-11-13 19:10:27 +01003101 gr->image_target_texture_2d =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04003102 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04003103
3104 extensions = (const char *) glGetString(GL_EXTENSIONS);
3105 if (!extensions) {
3106 weston_log("Retrieving GL extension string failed.\n");
3107 return -1;
3108 }
3109
Emil Velikovf0c3a1c2016-07-04 15:34:18 +01003110 if (!weston_check_egl_extension(extensions, "GL_EXT_texture_format_BGRA8888")) {
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04003111 weston_log("GL_EXT_texture_format_BGRA8888 not available\n");
3112 return -1;
3113 }
3114
Emil Velikovf0c3a1c2016-07-04 15:34:18 +01003115 if (weston_check_egl_extension(extensions, "GL_EXT_read_format_bgra"))
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01003116 ec->read_format = PIXMAN_a8r8g8b8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04003117 else
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01003118 ec->read_format = PIXMAN_a8b8g8r8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04003119
Emil Velikovf0c3a1c2016-07-04 15:34:18 +01003120 if (weston_check_egl_extension(extensions, "GL_EXT_unpack_subimage"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01003121 gr->has_unpack_subimage = 1;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04003122
Emil Velikovf0c3a1c2016-07-04 15:34:18 +01003123 if (weston_check_egl_extension(extensions, "GL_OES_EGL_image_external"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01003124 gr->has_egl_image_external = 1;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04003125
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04003126 glActiveTexture(GL_TEXTURE0);
3127
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02003128 if (compile_shaders(ec))
3129 return -1;
3130
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +03003131 gr->fragment_binding =
3132 weston_compositor_add_debug_binding(ec, KEY_S,
3133 fragment_debug_binding,
3134 ec);
3135 gr->fan_binding =
3136 weston_compositor_add_debug_binding(ec, KEY_F,
3137 fan_debug_repaint_binding,
3138 ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02003139
Pekka Paalanen035a0322012-10-24 09:43:06 +03003140 weston_log("GL ES 2 renderer features:\n");
3141 weston_log_continue(STAMP_SPACE "read-back format: %s\n",
Pekka Paalanenfe4eacf2013-01-10 16:50:42 +02003142 ec->read_format == PIXMAN_a8r8g8b8 ? "BGRA" : "RGBA");
Pekka Paalanen035a0322012-10-24 09:43:06 +03003143 weston_log_continue(STAMP_SPACE "wl_shm sub-image to texture: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01003144 gr->has_unpack_subimage ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03003145 weston_log_continue(STAMP_SPACE "EGL Wayland extension: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01003146 gr->has_bind_display ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03003147
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01003148
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04003149 return 0;
3150}
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03003151
3152WL_EXPORT struct gl_renderer_interface gl_renderer_interface = {
3153 .opaque_attribs = gl_renderer_opaque_attribs,
3154 .alpha_attribs = gl_renderer_alpha_attribs,
3155
3156 .create = gl_renderer_create,
3157 .display = gl_renderer_display,
3158 .output_create = gl_renderer_output_create,
3159 .output_destroy = gl_renderer_output_destroy,
3160 .output_surface = gl_renderer_output_surface,
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05003161 .output_set_border = gl_renderer_output_set_border,
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03003162 .print_egl_error_state = gl_renderer_print_egl_error_state
3163};