[PATCH v2] gles2-renderer: Provide an API for backends to use.

John Kåre Alsaker john.kare.alsaker at gmail.com
Fri Oct 26 09:06:15 PDT 2012


On Fri, Oct 26, 2012 at 3:59 PM, Kristian Høgsberg <hoegsberg at gmail.com> wrote:
> On Thu, Oct 25, 2012 at 10:53:20PM +0200, John Kåre Alsaker wrote:
>> This provides an new API for gles2-renderer. It allows to move most EGL initialization code and EGL surface creation into gles2-renderer, which makes compositor backends less dependent on gles2-renderer. As a side effect weston_output gets a per-renderer state which gles2-renderer uses to store the EGL surface.
>
> I read the patch and Pekka has a lot of good points, both stylistic
> and regarding the actual code changes.  However, I don't agree with
> the direction of the patch.  It's *ok* for a backend to know and
> depend on EGL or some other rendering API (say pixman or a custom
> compositing API or whatever).  It can even depend on multiple such
> APIs (for example both pixman and EGL).  A backend will always have to
> do some render API specific initialization, where the backend API and
> rendering API intersects.  Like eglGetDisplay, which requires backend
> specific knowledge (X display, gbm device or such) and rendering API
> knowledge (it's an EGL call).
What parts don't you agree with?
- Refactoring common EGL code into gles2-renderer.
- Providing a way for gles2-renderer to have output specific state.
- Moving EGL state from the compositor into gles2-renderer, which is
enabled by the above changes and happens to minimize code where the
backend API and rendering API intersects.

>
> The next small, self-contained step forward from where the renderer
> abstraction is now, is to move the EGL types out of the core structs
> and header files (that is, just compositor.h).  First step: move the
> shaders out of weston_compositor.h.  Let's do that and take the rest
> from there.
I could rebase out some smaller changes, but it's just more work and
wouldn't delay this patch by much.

Let's ignore the entry points catering to the Android hack and the
helper function and gles2_renderer_outputs_ready, all of which can go
away.

int
gles2_renderer_create(struct weston_compositor *ec,
EGLNativeDisplayType display, int alpha);
void
gles2_renderer_destroy(struct weston_compositor *ec);

struct gles2_output_state *
gles2_renderer_output_state_create(struct weston_compositor *ec,
EGLNativeWindowType window);
void
gles2_renderer_output_state_destroy(struct weston_compositor *ec,
struct gles2_output_state *go);

void
gles2_renderer_output_bind(struct weston_output *output, struct
gles2_output_state *go);
void
gles2_renderer_output_unbind(struct weston_output *output);

pq complained about the naming on bind/unbind. output_bind and
output_unbind binds the gl-renderer to an output, which is why the
renderer frees the state on unbind, since it no longer needs it.
gl_renderer_output_bind can never fail, that is why the output_state
has to be create and passed to it since creating an output_state can
fail. It's probably not the best naming, but I didn't come up with
anything better. They do not represent adding/removal of outputs as
the backends will do unbind followed by bind on mode switching.

As you can see, this API does depend on EGL so Kristian doesn't have
to worry that the backends are becoming EGL independent :)

>
> Kristian
>
>> ---
>>  src/compositor-android.c |  72 +++++++----------
>>  src/compositor-drm.c     |  87 ++++++---------------
>>  src/compositor-wayland.c |  58 +++-----------
>>  src/compositor-x11.c     |  71 +++--------------
>>  src/compositor.h         |  23 +++++-
>>  src/gles2-renderer.c     | 197 ++++++++++++++++++++++++++++++++++++++++++-----
>>  6 files changed, 265 insertions(+), 243 deletions(-)
>>
>> diff --git a/src/compositor-android.c b/src/compositor-android.c
>> index 3c0273a..bf14910 100644
>> --- a/src/compositor-android.c
>> +++ b/src/compositor-android.c
>> @@ -145,6 +145,8 @@ android_output_destroy(struct weston_output *base)
>>       wl_list_remove(&output->base.link);
>>       weston_output_destroy(&output->base);
>>
>> +     gles2_renderer_output_unbind(base);
>> +
>>       android_framebuffer_destroy(output->fb);
>>
>>       free(output);
>> @@ -319,6 +321,8 @@ android_seat_create(struct android_compositor *compositor)
>>  static int
>>  android_egl_choose_config(struct android_compositor *compositor,
>>                         struct android_framebuffer *fb,
>> +                       EGLDisplay egl_display,
>> +                       EGLConfig *egl_config,
>>                         const EGLint *attribs)
>>  {
>>       EGLBoolean ret;
>> @@ -332,9 +336,9 @@ android_egl_choose_config(struct android_compositor *compositor,
>>        * surfaceflinger/DisplayHardware/DisplayHardware.cpp
>>        */
>>
>> -     compositor->base.egl_config = NULL;
>> +     *egl_config = NULL;
>>
>> -     ret = eglGetConfigs(compositor->base.egl_display, NULL, 0, &count);
>> +     ret = eglGetConfigs(egl_display, NULL, 0, &count);
>>       if (ret == EGL_FALSE || count < 1)
>>               return -1;
>>
>> @@ -342,27 +346,27 @@ android_egl_choose_config(struct android_compositor *compositor,
>>       if (!configs)
>>               return -1;
>>
>> -     ret = eglChooseConfig(compositor->base.egl_display, attribs, configs,
>> +     ret = eglChooseConfig(egl_display, attribs, configs,
>>                             count, &matched);
>>       if (ret == EGL_FALSE || matched < 1)
>>               goto out;
>>
>>       for (i = 0; i < matched; ++i) {
>>               EGLint id;
>> -             ret = eglGetConfigAttrib(compositor->base.egl_display,
>> +             ret = eglGetConfigAttrib(egl_display,
>>                                        configs[i], EGL_NATIVE_VISUAL_ID,
>>                                        &id);
>>               if (ret == EGL_FALSE)
>>                       continue;
>>               if (id > 0 && fb->format == id) {
>> -                     compositor->base.egl_config = configs[i];
>> +                     *egl_config = configs[i];
>>                       break;
>>               }
>>       }
>>
>>  out:
>>       free(configs);
>> -     if (!compositor->base.egl_config)
>> +     if (!*egl_config)
>>               return -1;
>>
>>       return 0;
>> @@ -372,7 +376,8 @@ static int
>>  android_init_egl(struct android_compositor *compositor,
>>                struct android_output *output)
>>  {
>> -     EGLint eglmajor, eglminor;
>> +     EGLDisplay egl_display;
>> +     EGLConfig egl_config;
>>       int ret;
>>
>>       static const EGLint config_attrs[] = {
>> @@ -385,66 +390,41 @@ android_init_egl(struct android_compositor *compositor,
>>               EGL_NONE
>>       };
>>
>> -     compositor->base.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
>> -     if (compositor->base.egl_display == EGL_NO_DISPLAY) {
>> -             weston_log("Failed to create EGL display.\n");
>> -             print_egl_error_state();
>> -             return -1;
>> -     }
>> +     egl_display = gles2_renderer_init_without_config(&compositor->base, EGL_DEFAULT_DISPLAY);
>>
>> -     ret = eglInitialize(compositor->base.egl_display, &eglmajor, &eglminor);
>> -     if (!ret) {
>> -             weston_log("Failed to initialise EGL.\n");
>> +     if (egl_display == EGL_NO_DISPLAY) {
>> +             weston_log("Failed to create EGL display.\n");
>>               print_egl_error_state();
>>               return -1;
>>       }
>>
>> -     ret = android_egl_choose_config(compositor, output->fb, config_attrs);
>> +     ret = android_egl_choose_config(compositor, output->fb, egl_display, &egl_config, config_attrs);
>>       if (ret < 0) {
>>               weston_log("Failed to find an EGL config.\n");
>>               print_egl_error_state();
>>               return -1;
>>       }
>>
>> -     output->base.egl_surface =
>> -             eglCreateWindowSurface(compositor->base.egl_display,
>> -                                    compositor->base.egl_config,
>> -                                    output->fb->native_window,
>> -                                    NULL);
>> -     if (output->base.egl_surface == EGL_NO_SURFACE) {
>> -             weston_log("Failed to create FB EGLSurface.\n");
>> -             print_egl_error_state();
>> +     gles2_renderer_select_config(&compositor->base, egl_config);
>> +
>> +     if (gles2_renderer_output_state_create_and_bind(&output->base, output->fb->native_window) < 0)
>>               return -1;
>> -     }
>>
>>       return 0;
>>  }
>>
>>  static void
>> -android_fini_egl(struct android_compositor *compositor)
>> -{
>> -     gles2_renderer_destroy(&compositor->base);
>> -
>> -     eglMakeCurrent(compositor->base.egl_display,
>> -                    EGL_NO_SURFACE, EGL_NO_SURFACE,
>> -                    EGL_NO_CONTEXT);
>> -
>> -     eglTerminate(compositor->base.egl_display);
>> -     eglReleaseThread();
>> -}
>> -
>> -static void
>>  android_compositor_destroy(struct weston_compositor *base)
>>  {
>>       struct android_compositor *compositor = to_android_compositor(base);
>>
>>       android_seat_destroy(compositor->seat);
>>
>> +     gles2_renderer_destroy(base);
>> +
>>       /* destroys outputs, too */
>>       weston_compositor_shutdown(&compositor->base);
>>
>> -     android_fini_egl(compositor);
>> -
>>       free(compositor);
>>  }
>>
>> @@ -478,17 +458,17 @@ android_compositor_create(struct wl_display *display, int argc, char *argv[],
>>
>>       android_compositor_add_output(compositor, output);
>>
>> -     if (gles2_renderer_init(&compositor->base) < 0)
>> -             goto err_egl;
>> +     if (gles2_renderer_outputs_ready(&compositor->base) < 0)
>> +             goto err_gles2;
>>
>>       compositor->seat = android_seat_create(compositor);
>>       if (!compositor->seat)
>> -             goto err_egl;
>> +             goto err_gles2;
>>
>>       return &compositor->base;
>>
>> -err_egl:
>> -     android_fini_egl(compositor);
>> +err_gles2:
>> +     gles2_renderer_destroy(&compositor->base);
>>  err_output:
>>       android_output_destroy(&output->base);
>>  err_compositor:
>> diff --git a/src/compositor-drm.c b/src/compositor-drm.c
>> index 3e75387..96a206e 100644
>> --- a/src/compositor-drm.c
>> +++ b/src/compositor-drm.c
>> @@ -861,7 +861,7 @@ drm_output_destroy(struct weston_output *output_base)
>>       c->crtc_allocator &= ~(1 << output->crtc_id);
>>       c->connector_allocator &= ~(1 << output->connector_id);
>>
>> -     eglDestroySurface(c->base.egl_display, output->base.egl_surface);
>> +     gles2_renderer_output_unbind(output_base);
>>       gbm_surface_destroy(output->surface);
>>
>>       weston_plane_release(&output->fb_plane);
>> @@ -907,7 +907,7 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
>>       int ret;
>>       struct drm_compositor *ec;
>>       struct gbm_surface *surface;
>> -     EGLSurface egl_surface;
>> +     struct gles2_output_state *state;
>>
>>       if (output_base == NULL) {
>>               weston_log("output is NULL.\n");
>> @@ -967,15 +967,10 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
>>               return -1;
>>       }
>>
>> -     egl_surface =
>> -             eglCreateWindowSurface(ec->base.egl_display,
>> -                                    ec->base.egl_config,
>> -                                    surface, NULL);
>> +     state = gles2_renderer_output_state_create(&ec->base, surface);
>>
>> -     if (egl_surface == EGL_NO_SURFACE) {
>> -             weston_log("failed to create egl surface\n");
>> -             goto err;
>> -     }
>> +     if (!state)
>> +             goto err_gbm;
>>
>>       ret = drmModeSetCrtc(ec->drm.fd,
>>                            output->crtc_id,
>> @@ -983,7 +978,7 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
>>                            &output->connector_id, 1, &drm_mode->mode_info);
>>       if (ret) {
>>               weston_log("failed to set mode\n");
>> -             goto err;
>> +             goto err_gles2;
>>       }
>>
>>       /* reset rendering stuff. */
>> @@ -1005,10 +1000,10 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
>>       }
>>       output->next = NULL;
>>
>> -     eglDestroySurface(ec->base.egl_display, output->base.egl_surface);
>> +     gles2_renderer_output_unbind(output_base);
>>       gbm_surface_destroy(output->surface);
>> -     output->base.egl_surface = egl_surface;
>>       output->surface = surface;
>> +     gles2_renderer_output_bind(&output->base, state);
>>
>>       /*update output*/
>>       output->base.current = &drm_mode->base;
>> @@ -1016,8 +1011,9 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
>>       weston_output_move(&output->base, output->base.x, output->base.y);
>>       return 0;
>>
>> -err:
>> -     eglDestroySurface(ec->base.egl_display, egl_surface);
>> +err_gles2:
>> +     gles2_renderer_output_state_destroy(&ec->base, state);
>> +err_gbm:
>>       gbm_surface_destroy(surface);
>>       return -1;
>>  }
>> @@ -1039,18 +1035,8 @@ on_drm_input(int fd, uint32_t mask, void *data)
>>  static int
>>  init_egl(struct drm_compositor *ec, struct udev_device *device)
>>  {
>> -     EGLint major, minor, n;
>>       const char *filename, *sysnum;
>>       int fd;
>> -     static const EGLint config_attribs[] = {
>> -             EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
>> -             EGL_RED_SIZE, 1,
>> -             EGL_GREEN_SIZE, 1,
>> -             EGL_BLUE_SIZE, 1,
>> -             EGL_ALPHA_SIZE, 0,
>> -             EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
>> -             EGL_NONE
>> -     };
>>
>>       sysnum = udev_device_get_sysnum(device);
>>       if (sysnum)
>> @@ -1073,22 +1059,9 @@ init_egl(struct drm_compositor *ec, struct udev_device *device)
>>
>>       ec->drm.fd = fd;
>>       ec->gbm = gbm_create_device(ec->drm.fd);
>> -     ec->base.egl_display = eglGetDisplay(ec->gbm);
>> -     if (ec->base.egl_display == NULL) {
>> -             weston_log("failed to create display\n");
>> -             return -1;
>> -     }
>> -
>> -     if (!eglInitialize(ec->base.egl_display, &major, &minor)) {
>> -             weston_log("failed to initialize display\n");
>> -             return -1;
>> -     }
>>
>> -     if (!eglChooseConfig(ec->base.egl_display, config_attribs,
>> -                          &ec->base.egl_config, 1, &n) || n != 1) {
>> -             weston_log("failed to choose config: %d\n", n);
>> +     if (gles2_renderer_init(&ec->base, ec->gbm, 0) < 0)
>>               return -1;
>> -     }
>>
>>       return 0;
>>  }
>> @@ -1445,15 +1418,13 @@ create_output_for_connector(struct drm_compositor *ec,
>>               goto err_free;
>>       }
>>
>> -     output->base.egl_surface =
>> -             eglCreateWindowSurface(ec->base.egl_display,
>> -                                    ec->base.egl_config,
>> -                                    output->surface,
>> -                                    NULL);
>> -     if (output->base.egl_surface == EGL_NO_SURFACE) {
>> -             weston_log("failed to create egl surface\n");
>> -             goto err_surface;
>> -     }
>> +     weston_output_init(&output->base, &ec->base, x, y,
>> +                        connector->mmWidth, connector->mmHeight,
>> +                        o ? o->transform : WL_OUTPUT_TRANSFORM_NORMAL);
>> +
>> +     /* this requires output->base.compositor to be initialized */
>> +     if (gles2_renderer_output_state_create_and_bind(&output->base, output->surface) < 0)
>> +             goto err_output;
>>
>>       output->cursor_bo[0] =
>>               gbm_bo_create(ec->gbm, 64, 64, GBM_FORMAT_ARGB8888,
>> @@ -1473,10 +1444,6 @@ create_output_for_connector(struct drm_compositor *ec,
>>               output->base.backlight_current = drm_get_backlight(output);
>>       }
>>
>> -     weston_output_init(&output->base, &ec->base, x, y,
>> -                        connector->mmWidth, connector->mmHeight,
>> -                        o ? o->transform : WL_OUTPUT_TRANSFORM_NORMAL);
>> -
>>       wl_list_insert(ec->base.output_list.prev, &output->base.link);
>>
>>       output->base.origin = output->base.current;
>> @@ -1503,7 +1470,8 @@ create_output_for_connector(struct drm_compositor *ec,
>>
>>       return 0;
>>
>> -err_surface:
>> +err_output:
>> +     weston_output_destroy(&output->base);
>>       gbm_surface_destroy(output->surface);
>>  err_free:
>>       wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
>> @@ -2039,12 +2007,6 @@ drm_destroy(struct weston_compositor *ec)
>>
>>       gles2_renderer_destroy(ec);
>>
>> -     /* Work around crash in egl_dri2.c's dri2_make_current() */
>> -     eglMakeCurrent(ec->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
>> -                    EGL_NO_CONTEXT);
>> -     eglTerminate(ec->egl_display);
>> -     eglReleaseThread();
>> -
>>       gbm_device_destroy(d->gbm);
>>       destroy_sprites(d);
>>       if (weston_launcher_drm_set_master(&d->base, d->drm.fd, 0) < 0)
>> @@ -2238,7 +2200,7 @@ drm_compositor_create(struct wl_display *display,
>>               goto err_sprite;
>>       }
>>
>> -     if (gles2_renderer_init(&ec->base) < 0)
>> +     if (gles2_renderer_outputs_ready(&ec->base) < 0)
>>               goto err_egl;
>>
>>       path = NULL;
>> @@ -2280,10 +2242,7 @@ err_drm_source:
>>       wl_list_for_each_safe(weston_seat, next, &ec->base.seat_list, link)
>>               evdev_input_destroy(weston_seat);
>>  err_egl:
>> -     eglMakeCurrent(ec->base.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
>> -                    EGL_NO_CONTEXT);
>> -     eglTerminate(ec->base.egl_display);
>> -     eglReleaseThread();
>> +     gles2_renderer_destroy(&ec->base);
>>       gbm_device_destroy(ec->gbm);
>>  err_sprite:
>>       destroy_sprites(ec);
>> diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
>> index 56759fc..1e60d0f 100644
>> --- a/src/compositor-wayland.c
>> +++ b/src/compositor-wayland.c
>> @@ -241,41 +241,6 @@ create_border(struct wayland_compositor *c)
>>       pixman_image_unref(image);
>>  }
>>
>> -static int
>> -wayland_compositor_init_egl(struct wayland_compositor *c)
>> -{
>> -     EGLint major, minor;
>> -     EGLint n;
>> -     EGLint config_attribs[] = {
>> -             EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
>> -             EGL_RED_SIZE, 1,
>> -             EGL_GREEN_SIZE, 1,
>> -             EGL_BLUE_SIZE, 1,
>> -             EGL_ALPHA_SIZE, 1,
>> -             EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
>> -             EGL_NONE
>> -     };
>> -
>> -     c->base.egl_display = eglGetDisplay(c->parent.wl_display);
>> -     if (c->base.egl_display == NULL) {
>> -             weston_log("failed to create display\n");
>> -             return -1;
>> -     }
>> -
>> -     if (!eglInitialize(c->base.egl_display, &major, &minor)) {
>> -             weston_log("failed to initialize display\n");
>> -             return -1;
>> -     }
>> -
>> -     if (!eglChooseConfig(c->base.egl_display, config_attribs,
>> -                          &c->base.egl_config, 1, &n) || n == 0) {
>> -             weston_log("failed to choose config: %d\n", n);
>> -             return -1;
>> -     }
>> -
>> -     return 0;
>> -}
>> -
>>  static void
>>  frame_done(void *data, struct wl_callback *callback, uint32_t time)
>>  {
>> @@ -317,9 +282,9 @@ static void
>>  wayland_output_destroy(struct weston_output *output_base)
>>  {
>>       struct wayland_output *output = (struct wayland_output *) output_base;
>> -     struct weston_compositor *ec = output->base.compositor;
>>
>> -     eglDestroySurface(ec->egl_display, output->base.egl_surface);
>> +     gles2_renderer_output_unbind(output_base);
>> +
>>       wl_egl_window_destroy(output->parent.egl_window);
>>       free(output);
>>
>> @@ -373,13 +338,8 @@ wayland_compositor_create_output(struct wayland_compositor *c,
>>               goto cleanup_output;
>>       }
>>
>> -     output->base.egl_surface =
>> -             eglCreateWindowSurface(c->base.egl_display, c->base.egl_config,
>> -                                    output->parent.egl_window, NULL);
>> -     if (!output->base.egl_surface) {
>> -             weston_log("failed to create window surface\n");
>> +     if (gles2_renderer_output_state_create_and_bind(&output->base, output->parent.egl_window) < 0)
>>               goto cleanup_window;
>> -     }
>>
>>       output->parent.shell_surface =
>>               wl_shell_get_shell_surface(c->parent.shell,
>> @@ -831,7 +791,7 @@ wayland_compositor_create(struct wl_display *display,
>>       wl_display_dispatch(c->parent.wl_display);
>>
>>       c->base.wl_display = display;
>> -     if (wayland_compositor_init_egl(c) < 0)
>> +     if (gles2_renderer_init(&c->base, c->parent.wl_display, 1) < 0)
>>               goto err_display;
>>
>>       c->base.destroy = wayland_destroy;
>> @@ -844,11 +804,11 @@ wayland_compositor_create(struct wl_display *display,
>>
>>       /* requires border fields */
>>       if (wayland_compositor_create_output(c, width, height) < 0)
>> -             goto err_display;
>> +             goto err_gles2;
>>
>>       /* requires wayland_compositor_create_output */
>> -     if (gles2_renderer_init(&c->base) < 0)
>> -             goto err_display;
>> +     if (gles2_renderer_outputs_ready(&c->base) < 0)
>> +             goto err_gles2;
>>
>>       /* requires gles2_renderer_init */
>>       create_border(c);
>> @@ -860,12 +820,14 @@ wayland_compositor_create(struct wl_display *display,
>>               wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
>>                                    wayland_compositor_handle_event, c);
>>       if (c->parent.wl_source == NULL)
>> -             goto err_display;
>> +             goto err_gles2;
>>
>>       wl_event_source_check(c->parent.wl_source);
>>
>>       return &c->base;
>>
>> +err_gles2:
>> +     gles2_renderer_destroy(&c->base);
>>  err_display:
>>       wl_display_disconnect(c->parent.wl_display);
>>  err_compositor:
>> diff --git a/src/compositor-x11.c b/src/compositor-x11.c
>> index e616f45..80c28b0 100644
>> --- a/src/compositor-x11.c
>> +++ b/src/compositor-x11.c
>> @@ -239,53 +239,6 @@ x11_input_destroy(struct x11_compositor *compositor)
>>       weston_seat_release(&compositor->core_seat);
>>  }
>>
>> -static int
>> -x11_compositor_init_egl(struct x11_compositor *c)
>> -{
>> -     EGLint major, minor;
>> -     EGLint n;
>> -     EGLint config_attribs[] = {
>> -             EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
>> -             EGL_RED_SIZE, 1,
>> -             EGL_GREEN_SIZE, 1,
>> -             EGL_BLUE_SIZE, 1,
>> -             EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
>> -             EGL_NONE
>> -     };
>> -
>> -     c->base.egl_display = eglGetDisplay(c->dpy);
>> -     if (c->base.egl_display == NULL) {
>> -             weston_log("failed to create display\n");
>> -             return -1;
>> -     }
>> -
>> -     if (!eglInitialize(c->base.egl_display, &major, &minor)) {
>> -             weston_log("failed to initialize display\n");
>> -             return -1;
>> -     }
>> -
>> -     if (!eglChooseConfig(c->base.egl_display, config_attribs,
>> -                          &c->base.egl_config, 1, &n) || n == 0) {
>> -             weston_log("failed to choose config: %d\n", n);
>> -             return -1;
>> -     }
>> -
>> -     return 0;
>> -}
>> -
>> -static void
>> -x11_compositor_fini_egl(struct x11_compositor *compositor)
>> -{
>> -     gles2_renderer_destroy(&compositor->base);
>> -
>> -     eglMakeCurrent(compositor->base.egl_display,
>> -                    EGL_NO_SURFACE, EGL_NO_SURFACE,
>> -                    EGL_NO_CONTEXT);
>> -
>> -     eglTerminate(compositor->base.egl_display);
>> -     eglReleaseThread();
>> -}
>> -
>>  static void
>>  x11_output_repaint(struct weston_output *output_base,
>>                  pixman_region32_t *damage)
>> @@ -322,8 +275,7 @@ x11_output_destroy(struct weston_output *output_base)
>>       wl_list_remove(&output->base.link);
>>       wl_event_source_remove(output->finish_frame_timer);
>>
>> -     eglDestroySurface(compositor->base.egl_display,
>> -                       output->base.egl_surface);
>> +     gles2_renderer_output_unbind(output_base);
>>
>>       xcb_destroy_window(compositor->conn, output->window);
>>
>> @@ -529,13 +481,8 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
>>               x11_output_change_state(output, 1,
>>                                       c->atom.net_wm_state_fullscreen);
>>
>> -     output->base.egl_surface =
>> -             eglCreateWindowSurface(c->base.egl_display, c->base.egl_config,
>> -                                    output->window, NULL);
>> -     if (!output->base.egl_surface) {
>> -             weston_log("failed to create window surface\n");
>> +     if (gles2_renderer_output_state_create_and_bind(&output->base, output->window) < 0)
>>               return NULL;
>> -     }
>>
>>       loop = wl_display_get_event_loop(c->base.wl_display);
>>       output->finish_frame_timer =
>> @@ -1085,7 +1032,7 @@ x11_destroy(struct weston_compositor *ec)
>>
>>       weston_compositor_shutdown(ec); /* destroys outputs, too */
>>
>> -     x11_compositor_fini_egl(compositor);
>> +     gles2_renderer_destroy(ec);
>>
>>       XCloseDisplay(compositor->dpy);
>>       free(ec);
>> @@ -1133,14 +1080,14 @@ x11_compositor_create(struct wl_display *display,
>>       x11_compositor_get_resources(c);
>>
>>       c->base.wl_display = display;
>> -     if (x11_compositor_init_egl(c) < 0)
>> +     if (gles2_renderer_init(&c->base, c->dpy, 0) < 0)
>>               goto err_xdisplay;
>>
>>       c->base.destroy = x11_destroy;
>>       c->base.restore = x11_restore;
>>
>>       if (x11_input_create(c, no_input) < 0)
>> -             goto err_egl;
>> +             goto err_gles2;
>>
>>       width = option_width ? option_width : 1024;
>>       height = option_height ? option_height : 640;
>> @@ -1173,8 +1120,8 @@ x11_compositor_create(struct wl_display *display,
>>               x = pixman_region32_extents(&output->base.region)->x2;
>>       }
>>
>> -     if (gles2_renderer_init(&c->base) < 0)
>> -             goto err_egl;
>> +     if (gles2_renderer_outputs_ready(&c->base) < 0)
>> +             goto err_x11_input;
>>
>>       c->xcb_source =
>>               wl_event_loop_add_fd(c->base.input_loop,
>> @@ -1187,8 +1134,8 @@ x11_compositor_create(struct wl_display *display,
>>
>>  err_x11_input:
>>       x11_input_destroy(c);
>> -err_egl:
>> -     x11_compositor_fini_egl(c);
>> +err_gles2:
>> +     gles2_renderer_destroy(&c->base);
>>  err_xdisplay:
>>       XCloseDisplay(c->dpy);
>>  err_free:
>> diff --git a/src/compositor.h b/src/compositor.h
>> index 3176bfd..59eb4bf 100644
>> --- a/src/compositor.h
>> +++ b/src/compositor.h
>> @@ -154,7 +154,8 @@ enum dpms_enum {
>>  struct weston_output {
>>       uint32_t id;
>>
>> -     EGLSurface egl_surface;
>> +     void *renderer_state;
>> +
>>       struct wl_list link;
>>       struct wl_list resource_list;
>>       struct wl_global *global;
>> @@ -822,8 +823,26 @@ weston_surface_destroy(struct weston_surface *surface);
>>  int
>>  weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode);
>>
>> +struct gles2_output_state;
>> +
>> +int
>> +gles2_renderer_init(struct weston_compositor *ec, EGLNativeDisplayType display, int alpha);
>> +EGLDisplay
>> +gles2_renderer_init_without_config(struct weston_compositor *ec, EGLNativeDisplayType display);
>> +void
>> +gles2_renderer_select_config(struct weston_compositor *ec, EGLConfig config);
>>  int
>> -gles2_renderer_init(struct weston_compositor *ec);
>> +gles2_renderer_outputs_ready(struct weston_compositor *ec);
>> +int
>> +gles2_renderer_output_state_create_and_bind(struct weston_output *output, EGLNativeWindowType window);
>> +struct gles2_output_state *
>> +gles2_renderer_output_state_create(struct weston_compositor *ec, EGLNativeWindowType window);
>> +void
>> +gles2_renderer_output_state_destroy(struct weston_compositor *ec, struct gles2_output_state *state);
>> +void
>> +gles2_renderer_output_bind(struct weston_output *output, struct gles2_output_state *state);
>> +void
>> +gles2_renderer_output_unbind(struct weston_output *output);
>>  void
>>  gles2_renderer_destroy(struct weston_compositor *ec);
>>
>> diff --git a/src/gles2-renderer.c b/src/gles2-renderer.c
>> index 544cc15..a03a7dd 100644
>> --- a/src/gles2-renderer.c
>> +++ b/src/gles2-renderer.c
>> @@ -30,6 +30,26 @@
>>
>>  #include "compositor.h"
>>
>> +struct gles2_output_state {
>> +     EGLSurface egl_surface;
>> +};
>> +
>> +struct gles2_renderer {
>> +     struct weston_renderer base;
>> +};
>> +
>> +static inline struct gles2_output_state *
>> +get_output_state(struct weston_output *output)
>> +{
>> +     return (struct gles2_output_state *)output->renderer_state;
>> +}
>> +
>> +static inline struct gles2_renderer *
>> +get_renderer(struct weston_compositor *ec)
>> +{
>> +     return (struct gles2_renderer *)ec->renderer;
>> +}
>> +
>>  static const char *
>>  egl_error_string(EGLint code)
>>  {
>> @@ -700,6 +720,7 @@ static void
>>  gles2_renderer_repaint_output(struct weston_output *output,
>>                             pixman_region32_t *output_damage)
>>  {
>> +     struct gles2_output_state *output_state = get_output_state(output);
>>       struct weston_compositor *compositor = output->compositor;
>>       EGLBoolean ret;
>>       static int errored;
>> @@ -712,8 +733,8 @@ gles2_renderer_repaint_output(struct weston_output *output,
>>
>>       glViewport(0, 0, width, height);
>>
>> -     ret = eglMakeCurrent(compositor->egl_display, output->egl_surface,
>> -                          output->egl_surface, compositor->egl_context);
>> +     ret = eglMakeCurrent(compositor->egl_display, output_state->egl_surface,
>> +                          output_state->egl_surface, compositor->egl_context);
>>       if (ret == EGL_FALSE) {
>>               if (errored)
>>                       return;
>> @@ -749,7 +770,7 @@ gles2_renderer_repaint_output(struct weston_output *output,
>>
>>       wl_signal_emit(&output->frame_signal, output);
>>
>> -     ret = eglSwapBuffers(compositor->egl_display, output->egl_surface);
>> +     ret = eglSwapBuffers(compositor->egl_display, output_state->egl_surface);
>>       if (ret == EGL_FALSE && !errored) {
>>               errored = 1;
>>               weston_log("Failed in eglSwapBuffers.\n");
>> @@ -1157,24 +1178,167 @@ log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
>>               weston_log_continue(" unknown\n");
>>  }
>>
>> -struct gles2_renderer {
>> -     struct weston_renderer base;
>> -};
>> +static int
>> +create_renderer(struct weston_compositor *ec)
>> +{
>> +     struct gles2_renderer *renderer = malloc(sizeof *renderer);
>> +
>> +     if (renderer == NULL)
>> +             return -1;
>> +
>> +     renderer->base.repaint_output = gles2_renderer_repaint_output;
>> +     renderer->base.flush_damage = gles2_renderer_flush_damage;
>> +     renderer->base.attach = gles2_renderer_attach;
>> +     renderer->base.destroy_surface = gles2_renderer_destroy_surface;
>> +
>> +     ec->renderer = &renderer->base;
>> +
>> +     return 0;
>> +}
>> +
>> +static int
>> +init_display(struct weston_compositor *ec, EGLNativeDisplayType display)
>> +{
>> +     EGLint major, minor;
>> +
>> +     if (create_renderer(ec) < 0)
>> +             return -1;
>> +
>> +     ec->egl_display = eglGetDisplay(display);
>> +     if (ec->egl_display == NULL) {
>> +             weston_log("failed to create display\n");
>> +             print_egl_error_state();
>> +             return -1;
>> +     }
>> +
>> +     if (!eglInitialize(ec->egl_display, &major, &minor)) {
>> +             weston_log("failed to initialize display\n");
>> +             print_egl_error_state();
>> +             return -1;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +WL_EXPORT int
>> +gles2_renderer_output_state_create_and_bind(struct weston_output *output, EGLNativeWindowType window)
>> +{
>> +     struct gles2_output_state *state = gles2_renderer_output_state_create(output->compositor, window);
>> +
>> +     if (!state)
>> +             return -1;
>> +
>> +     gles2_renderer_output_bind(output, state);
>> +
>> +     return 0;
>> +}
>> +
>> +WL_EXPORT struct gles2_output_state *
>> +gles2_renderer_output_state_create(struct weston_compositor *ec, EGLNativeWindowType window)
>> +{
>> +     struct gles2_output_state *state = calloc(1, sizeof *state);
>> +
>> +     if (!state)
>> +             return NULL;
>> +
>> +     state->egl_surface =
>> +             eglCreateWindowSurface(ec->egl_display,
>> +                                    ec->egl_config,
>> +                                    window, NULL);
>> +
>> +     if (state->egl_surface == EGL_NO_SURFACE) {
>> +             weston_log("failed to create egl surface\n");
>> +             free(state);
>> +             return NULL;
>> +     }
>> +
>> +     return state;
>> +}
>> +
>> +WL_EXPORT void
>> +gles2_renderer_output_state_destroy(struct weston_compositor *ec, struct gles2_output_state *state)
>> +{
>> +     eglDestroySurface(ec->egl_display, state->egl_surface);
>> +
>> +     free(state);
>> +}
>> +
>> +WL_EXPORT void
>> +gles2_renderer_output_bind(struct weston_output *output, struct gles2_output_state *state)
>> +{
>> +     output->renderer_state = state;
>> +}
>> +
>> +WL_EXPORT void
>> +gles2_renderer_output_unbind(struct weston_output *output)
>> +{
>> +     gles2_renderer_output_state_destroy(output->compositor, get_output_state(output));
>> +}
>>
>>  WL_EXPORT void
>>  gles2_renderer_destroy(struct weston_compositor *ec)
>>  {
>>       if (ec->has_bind_display)
>>               ec->unbind_display(ec->egl_display, ec->wl_display);
>> +
>> +     /* Work around crash in egl_dri2.c's dri2_make_current() - when does this apply? */
>> +     eglMakeCurrent(ec->egl_display,
>> +                    EGL_NO_SURFACE, EGL_NO_SURFACE,
>> +                    EGL_NO_CONTEXT);
>> +
>> +     eglTerminate(ec->egl_display);
>> +     eglReleaseThread();
>> +}
>> +
>> +WL_EXPORT int
>> +gles2_renderer_init(struct weston_compositor *ec, EGLNativeDisplayType display, int alpha)
>> +{
>> +     EGLint n;
>> +
>> +     const EGLint config_attribs[] = {
>> +             EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
>> +             EGL_RED_SIZE, 1,
>> +             EGL_GREEN_SIZE, 1,
>> +             EGL_BLUE_SIZE, 1,
>> +             EGL_ALPHA_SIZE, alpha ? 1 : 0,
>> +             EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
>> +             EGL_NONE
>> +     };
>> +
>> +     if (init_display(ec, display) < 0)
>> +             return -1;
>> +
>> +     if (!eglChooseConfig(ec->egl_display, config_attribs,
>> +                          &ec->egl_config, 1, &n) || n != 1) {
>> +             weston_log("failed to choose config: %d\n", n);
>> +             print_egl_error_state();
>> +             return -1;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +WL_EXPORT EGLDisplay
>> +gles2_renderer_init_without_config(struct weston_compositor *ec, EGLNativeDisplayType display)
>> +{
>> +     if (init_display(ec, display) < 0)
>> +             return EGL_NO_DISPLAY;
>> +     else
>> +             return ec->egl_display;
>> +}
>> +
>> +void
>> +gles2_renderer_select_config(struct weston_compositor *ec, EGLConfig config)
>> +{
>> +     ec->egl_config = config;
>>  }
>>
>>  WL_EXPORT int
>> -gles2_renderer_init(struct weston_compositor *ec)
>> +gles2_renderer_outputs_ready(struct weston_compositor *ec)
>>  {
>> -     struct gles2_renderer *renderer;
>>       const char *extensions;
>>       int has_egl_image_external = 0;
>> -     struct weston_output *output;
>> +     struct gles2_output_state *output;
>>       EGLBoolean ret;
>>
>>       static const EGLint context_attribs[] = {
>> @@ -1182,10 +1346,6 @@ gles2_renderer_init(struct weston_compositor *ec)
>>               EGL_NONE
>>       };
>>
>> -     renderer = malloc(sizeof *renderer);
>> -     if (renderer == NULL)
>> -             return -1;
>> -
>>       if (!eglBindAPI(EGL_OPENGL_ES_API)) {
>>               weston_log("failed to bind EGL_OPENGL_ES_API\n");
>>               print_egl_error_state();
>> @@ -1202,8 +1362,8 @@ gles2_renderer_init(struct weston_compositor *ec)
>>               return -1;
>>       }
>>
>> -     output = container_of(ec->output_list.next,
>> -                           struct weston_output, link);
>> +     output = get_output_state(container_of(ec->output_list.next,
>> +                           struct weston_output, link));
>>       ret = eglMakeCurrent(ec->egl_display, output->egl_surface,
>>                            output->egl_surface, ec->egl_context);
>>       if (ret == EGL_FALSE) {
>> @@ -1289,12 +1449,6 @@ gles2_renderer_init(struct weston_compositor *ec)
>>                            vertex_shader, solid_fragment_shader) < 0)
>>               return -1;
>>
>> -     renderer->base.repaint_output = gles2_renderer_repaint_output;
>> -     renderer->base.flush_damage = gles2_renderer_flush_damage;
>> -     renderer->base.attach = gles2_renderer_attach;
>> -     renderer->base.destroy_surface = gles2_renderer_destroy_surface;
>> -     ec->renderer = &renderer->base;
>> -
>>       weston_log("GL ES 2 renderer features:\n");
>>       weston_log_continue(STAMP_SPACE "read-back format: %s\n",
>>                           ec->read_format == GL_BGRA_EXT ? "BGRA" : "RGBA");
>> @@ -1303,5 +1457,6 @@ gles2_renderer_init(struct weston_compositor *ec)
>>       weston_log_continue(STAMP_SPACE "EGL Wayland extension: %s\n",
>>                           ec->has_bind_display ? "yes" : "no");
>>
>> +
>>       return 0;
>>  }
>> --
>> 1.7.12.4
>>
>> _______________________________________________
>> wayland-devel mailing list
>> wayland-devel at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list