The gbm-format configuration option can now be specified per-output as
well as in the core config section. If it is not specified it will
default to the format specified in the core section. The
EGL_MESA_configless_context extension is required for this to work. If
this extension is available it will create a context without an
EGLConfig and then it will potentially use a different EGLConfig for
each output.

The gl-renderer interface has been changed so that it takes the EGL
attributes and visual ID in the create_output function as well as in
the create function.
---
 src/compositor-drm.c     |  65 ++++++++++++++++-------
 src/compositor-fbdev.c   |   4 +-
 src/compositor-wayland.c |   4 +-
 src/compositor-x11.c     |   4 +-
 src/gl-renderer.c        | 134 +++++++++++++++++++++++++++++------------------
 src/gl-renderer.h        |   4 +-
 6 files changed, 141 insertions(+), 74 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index e45f47d..3f584a6 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;
@@ -1853,6 +1855,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,
                            drmModeConnector *connector,
@@ -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 0d96269..d1013e8 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 899c329..238946b 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 6b5eb64..125875e 100644
--- a/src/compositor-x11.c
+++ b/src/compositor-x11.c
@@ -889,7 +889,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 868fdb7..29d96f3 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;
 }
 
@@ -1775,50 +1842,6 @@ gl_renderer_destroy(struct weston_compositor *ec)
 }
 
 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)
 {
        struct gl_renderer *gr = get_renderer(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 dcdf69d..db42f6c 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);
 
-- 
1.8.5.3

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to