diff --git a/src/compositor-drm.c b/src/compositor-drm.c index e45f47d4..3f584a66 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -147,6 +147,7 @@ struct drm_output { drmModeCrtcPtr original_crtc; struct drm_edid edid; drmModePropertyPtr dpms_prop; + uint32_t format; int vblank_pending; int page_flip_pending; @@ -420,8 +421,6 @@ static uint32_t drm_output_check_scanout_format(struct drm_output *output, struct weston_surface *es, struct gbm_bo *bo) { - struct drm_compositor *c = - (struct drm_compositor *) output->base.compositor; uint32_t format; pixman_region32_t r; @@ -442,7 +441,7 @@ drm_output_check_scanout_format(struct drm_output *output, pixman_region32_fini(&r); } - if (c->format == format) + if (output->format == format) return format; return 0; @@ -507,7 +506,7 @@ drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage) return; } - output->next = drm_fb_get_from_bo(bo, c, c->format); + output->next = drm_fb_get_from_bo(bo, c, output->format); if (!output->next) { weston_log("failed to get drm_fb for bo\n"); gbm_surface_release_buffer(output->surface, bo); @@ -1528,12 +1527,13 @@ find_crtc_for_connector(struct drm_compositor *ec, static int drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec) { + EGLint format = output->format; int i, flags; output->surface = gbm_surface_create(ec->gbm, output->base.current_mode->width, output->base.current_mode->height, - ec->format, + format, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); if (!output->surface) { @@ -1541,7 +1541,9 @@ drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec) return -1; } - if (gl_renderer->output_create(&output->base, output->surface) < 0) { + if (gl_renderer->output_create(&output->base, output->surface, + gl_renderer->opaque_attribs, + &format) < 0) { weston_log("failed to create gl renderer output state\n"); gbm_surface_destroy(output->surface); return -1; @@ -1852,6 +1854,35 @@ setup_output_seat_constraint(struct drm_compositor *ec, } } +static int +get_gbm_format_from_section(struct weston_config_section *section, + uint32_t default_value, + uint32_t *format) +{ + char *s; + int ret = 0; + + weston_config_section_get_string(section, + "gbm-format", &s, NULL); + + if (s == NULL) + *format = default_value; + else if (strcmp(s, "xrgb8888") == 0) + *format = GBM_FORMAT_XRGB8888; + else if (strcmp(s, "rgb565") == 0) + *format = GBM_FORMAT_RGB565; + else if (strcmp(s, "xrgb2101010") == 0) + *format = GBM_FORMAT_XRGB2101010; + else { + weston_log("fatal: unrecognized pixel format: %s\n", s); + ret = -1; + } + + free(s); + + return ret; +} + static int create_output_for_connector(struct drm_compositor *ec, drmModeRes *resources, @@ -1919,6 +1950,11 @@ create_output_for_connector(struct drm_compositor *ec, transform = parse_transform(s, output->base.name); free(s); + if (get_gbm_format_from_section(section, + ec->format, + &output->format) == -1) + output->format = ec->format; + weston_config_section_get_string(section, "seat", &s, ""); setup_output_seat_constraint(ec, &output->base, s); free(s); @@ -2663,7 +2699,6 @@ drm_compositor_create(struct wl_display *display, struct udev_device *drm_device; struct wl_event_loop *loop; const char *path; - char *s; uint32_t key; weston_log("initializing drm backend\n"); @@ -2677,20 +2712,10 @@ drm_compositor_create(struct wl_display *display, ec->sprites_are_broken = 1; section = weston_config_get_section(config, "core", NULL, NULL); - weston_config_section_get_string(section, - "gbm-format", &s, "xrgb8888"); - if (strcmp(s, "xrgb8888") == 0) - ec->format = GBM_FORMAT_XRGB8888; - else if (strcmp(s, "rgb565") == 0) - ec->format = GBM_FORMAT_RGB565; - else if (strcmp(s, "xrgb2101010") == 0) - ec->format = GBM_FORMAT_XRGB2101010; - else { - weston_log("fatal: unrecognized pixel format: %s\n", s); - free(s); + if (get_gbm_format_from_section(section, + GBM_FORMAT_XRGB8888, + &ec->format) == -1) goto err_base; - } - free(s); ec->use_pixman = param->use_pixman; diff --git a/src/compositor-fbdev.c b/src/compositor-fbdev.c index 0d962693..d1013e8b 100644 --- a/src/compositor-fbdev.c +++ b/src/compositor-fbdev.c @@ -628,7 +628,9 @@ fbdev_output_create(struct fbdev_compositor *compositor, } else { setenv("HYBRIS_EGLPLATFORM", "wayland", 1); if (gl_renderer->output_create(&output->base, - (EGLNativeWindowType)NULL) < 0) { + (EGLNativeWindowType)NULL, + gl_renderer->opaque_attribs, + NULL) < 0) { weston_log("gl_renderer_output_create failed.\n"); goto out_shadow_surface; } diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c index 899c3293..238946b2 100644 --- a/src/compositor-wayland.c +++ b/src/compositor-wayland.c @@ -593,7 +593,9 @@ wayland_output_init_gl_renderer(struct wayland_output *output) } if (gl_renderer->output_create(&output->base, - output->gl.egl_window) < 0) + output->gl.egl_window, + gl_renderer->alpha_attribs, + NULL) < 0) goto cleanup_window; return 0; diff --git a/src/compositor-x11.c b/src/compositor-x11.c index ffbef400..ce1c0711 100644 --- a/src/compositor-x11.c +++ b/src/compositor-x11.c @@ -890,7 +890,9 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y, } } else { ret = gl_renderer->output_create(&output->base, - (EGLNativeWindowType) output->window); + (EGLNativeWindowType) output->window, + gl_renderer->opaque_attribs, + NULL); if (ret < 0) return NULL; } diff --git a/src/gl-renderer.c b/src/gl-renderer.c index 868fdb71..29d96f3c 100644 --- a/src/gl-renderer.c +++ b/src/gl-renderer.c @@ -139,6 +139,8 @@ struct gl_renderer { int has_egl_buffer_age; + int has_configless_context; + struct gl_shader texture_shader_rgba; struct gl_shader texture_shader_rgbx; struct gl_shader texture_shader_egl_external; @@ -1658,6 +1660,51 @@ log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig) weston_log_continue(" unknown\n"); } +static int +egl_choose_config(struct gl_renderer *gr, const EGLint *attribs, + const EGLint *visual_id, + EGLConfig *config_out) +{ + EGLint count = 0; + EGLint matched = 0; + EGLConfig *configs; + int i; + + if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1) + return -1; + + configs = calloc(count, sizeof *configs); + if (!configs) + return -1; + + if (!eglChooseConfig(gr->egl_display, attribs, configs, + count, &matched)) + goto out; + + for (i = 0; i < matched; ++i) { + EGLint id; + + if (visual_id) { + if (!eglGetConfigAttrib(gr->egl_display, + configs[i], EGL_NATIVE_VISUAL_ID, + &id)) + continue; + + if (id != 0 && id != *visual_id) + continue; + } + + *config_out = configs[i]; + + free(configs); + return 0; + } + +out: + free(configs); + return -1; +} + static void gl_renderer_output_set_border(struct weston_output *output, enum gl_renderer_border_side side, @@ -1689,19 +1736,37 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface); static int gl_renderer_output_create(struct weston_output *output, - EGLNativeWindowType window) + EGLNativeWindowType window, + const EGLint *attribs, + const EGLint *visual_id) { struct weston_compositor *ec = output->compositor; struct gl_renderer *gr = get_renderer(ec); - struct gl_output_state *go = calloc(1, sizeof *go); + struct gl_output_state *go; + EGLConfig egl_config; int i; + if (egl_choose_config(gr, attribs, visual_id, &egl_config) == -1) { + weston_log("failed to choose EGL config for output\n"); + return -1; + } + + if (egl_config != gr->egl_config && + !gr->has_configless_context) { + weston_log("attempted to use a different EGL config for an " + "output but EGL_MESA_configless_context is not " + "supported\n"); + return -1; + } + + go = calloc(1, sizeof *go); + if (!go) return -1; go->egl_surface = eglCreateWindowSurface(gr->egl_display, - gr->egl_config, + egl_config, window, NULL); if (go->egl_surface == EGL_NO_SURFACE) { @@ -1721,6 +1786,8 @@ gl_renderer_output_create(struct weston_output *output, output->renderer_state = go; + log_egl_config_info(gr->egl_display, egl_config); + return 0; } @@ -1774,50 +1841,6 @@ gl_renderer_destroy(struct weston_compositor *ec) free(gr); } -static int -egl_choose_config(struct gl_renderer *gr, const EGLint *attribs, - const EGLint *visual_id) -{ - EGLint count = 0; - EGLint matched = 0; - EGLConfig *configs; - int i; - - if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1) - return -1; - - configs = calloc(count, sizeof *configs); - if (!configs) - return -1; - - if (!eglChooseConfig(gr->egl_display, attribs, configs, - count, &matched)) - goto out; - - for (i = 0; i < matched; ++i) { - EGLint id; - - if (visual_id) { - if (!eglGetConfigAttrib(gr->egl_display, - configs[i], EGL_NATIVE_VISUAL_ID, - &id)) - continue; - - if (id != 0 && id != *visual_id) - continue; - } - - gr->egl_config = configs[i]; - - free(configs); - return 0; - } - -out: - free(configs); - return -1; -} - static int gl_renderer_setup_egl_extensions(struct weston_compositor *ec) { @@ -1864,6 +1887,11 @@ gl_renderer_setup_egl_extensions(struct weston_compositor *ec) "supported. Performance could be affected.\n"); #endif +#ifdef EGL_MESA_configless_context + if (strstr(extensions, "EGL_MESA_configless_context")) + gr->has_configless_context = 1; +#endif + return 0; } @@ -1917,7 +1945,7 @@ gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display, goto err_egl; } - if (egl_choose_config(gr, attribs, visual_id) < 0) { + if (egl_choose_config(gr, attribs, visual_id, &gr->egl_config) < 0) { weston_log("failed to choose EGL config\n"); goto err_egl; } @@ -2021,6 +2049,7 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface) { struct gl_renderer *gr = get_renderer(ec); const char *extensions; + EGLConfig context_config; EGLBoolean ret; static const EGLint context_attribs[] = { @@ -2034,9 +2063,14 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface) return -1; } - log_egl_config_info(gr->egl_display, gr->egl_config); + context_config = gr->egl_config; + +#ifdef EGL_MESA_configless_context + if (gr->has_configless_context) + context_config = EGL_NO_CONFIG_MESA; +#endif - gr->egl_context = eglCreateContext(gr->egl_display, gr->egl_config, + gr->egl_context = eglCreateContext(gr->egl_display, context_config, EGL_NO_CONTEXT, context_attribs); if (gr->egl_context == NULL) { weston_log("failed to create context\n"); diff --git a/src/gl-renderer.h b/src/gl-renderer.h index dcdf69d8..db42f6ca 100644 --- a/src/gl-renderer.h +++ b/src/gl-renderer.h @@ -58,7 +58,9 @@ struct gl_renderer_interface { EGLDisplay (*display)(struct weston_compositor *ec); int (*output_create)(struct weston_output *output, - EGLNativeWindowType window); + EGLNativeWindowType window, + const EGLint *attribs, + const EGLint *visual_id); void (*output_destroy)(struct weston_output *output);