Actually moving the GL and EGL state is done in a separate commit in the interest of clarity and reducing conflicts.
This commit enables 3 EGL fields to be moved into gles2-renderer, of which only 1 field is required to move. I suggest one of the following options to continue: - Backport the moving of the two other EGL fields which this commit enabled to move or more, so you feel like the changes are more justified. - Split the commit in two so the EGL refactorings and output API addition is on separate commits. Perhaps in combination with backporting on the EGL refactorings part. - Submit the entire patch set which moves all GL and EGL state into gles2-renderer, which gets treated as one patch. - Submit the patch set as one patch (That'll be fun to review). On Fri, Oct 26, 2012 at 8:56 PM, Kristian Høgsberg <hoegsb...@gmail.com> wrote: > On Fri, Oct 26, 2012 at 02:39:24PM -0400, Kristian Høgsberg wrote: >> On Fri, Oct 26, 2012 at 06:06:15PM +0200, John Kåre Alsaker wrote: >> > On Fri, Oct 26, 2012 at 3:59 PM, Kristian Høgsberg <hoegsb...@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. >> >> I guess we're at a stalemate then. > > To elaborate, I don't think my suggestion was any kind of ambiguous. > I don't want to see new patches that introduce 10 new interal API > entrypoints without even moving the EGL types out of compositor.h. > > Kristian > >> >> > 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@lists.freedesktop.org >> > >> http://lists.freedesktop.org/mailman/listinfo/wayland-devel _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel