diff --git a/src/compositor-android.c b/src/compositor-android.c index 5bf1df3f..cced65de 100644 --- a/src/compositor-android.c +++ b/src/compositor-android.c @@ -78,42 +78,6 @@ to_android_compositor(struct weston_compositor *base) return container_of(base, struct android_compositor, base); } -static const char * -egl_error_string(EGLint code) -{ -#define MYERRCODE(x) case x: return #x; - switch (code) { - MYERRCODE(EGL_SUCCESS) - MYERRCODE(EGL_NOT_INITIALIZED) - MYERRCODE(EGL_BAD_ACCESS) - MYERRCODE(EGL_BAD_ALLOC) - MYERRCODE(EGL_BAD_ATTRIBUTE) - MYERRCODE(EGL_BAD_CONTEXT) - MYERRCODE(EGL_BAD_CONFIG) - MYERRCODE(EGL_BAD_CURRENT_SURFACE) - MYERRCODE(EGL_BAD_DISPLAY) - MYERRCODE(EGL_BAD_SURFACE) - MYERRCODE(EGL_BAD_MATCH) - MYERRCODE(EGL_BAD_PARAMETER) - MYERRCODE(EGL_BAD_NATIVE_PIXMAP) - MYERRCODE(EGL_BAD_NATIVE_WINDOW) - MYERRCODE(EGL_CONTEXT_LOST) - default: - return "unknown"; - } -#undef MYERRCODE -} - -static void -print_egl_error_state(void) -{ - EGLint code; - - code = eglGetError(); - weston_log("EGL error state: %s (0x%04lx)\n", - egl_error_string(code), (long)code); -} - static void android_finish_frame(void *data) { @@ -318,116 +282,26 @@ android_seat_create(struct android_compositor *compositor) return seat; } -static int -android_egl_choose_config(struct android_compositor *compositor, - struct android_framebuffer *fb, - const EGLint *attribs) -{ - EGLBoolean ret; - EGLint count = 0; - EGLint matched = 0; - EGLConfig *configs; - int i; - - /* - * The logic is copied from Android frameworks/base/services/ - * surfaceflinger/DisplayHardware/DisplayHardware.cpp - */ - - compositor->base.egl_config = NULL; - - ret = eglGetConfigs(compositor->base.egl_display, NULL, 0, &count); - if (ret == EGL_FALSE || count < 1) - return -1; - - configs = calloc(count, sizeof *configs); - if (!configs) - return -1; - - ret = eglChooseConfig(compositor->base.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, - configs[i], EGL_NATIVE_VISUAL_ID, - &id); - if (ret == EGL_FALSE) - continue; - if (id > 0 && fb->format == id) { - compositor->base.egl_config = configs[i]; - break; - } - } - -out: - free(configs); - if (!compositor->base.egl_config) - return -1; - - return 0; -} - static int android_init_egl(struct android_compositor *compositor, struct android_output *output) { - EGLint eglmajor, eglminor; - int ret; + EGLint visual_id = output->fb->format; - static const EGLint config_attrs[] = { - 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 - }; - - 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(); + if (gles2_renderer_create(&compositor->base, + EGL_DEFAULT_DISPLAY, gles2_renderer_opaque_attribs, + &visual_id) < 0) return -1; - } - - ret = eglInitialize(compositor->base.egl_display, &eglmajor, &eglminor); - if (!ret) { - weston_log("Failed to initialise EGL.\n"); - print_egl_error_state(); - return -1; - } - - ret = android_egl_choose_config(compositor, output->fb, config_attrs); - if (ret < 0) { - weston_log("Failed to find an EGL config.\n"); - print_egl_error_state(); - return -1; - } if (gles2_renderer_output_create(&output->base, - output->fb->native_window) < 0) + output->fb->native_window) < 0) { + gles2_renderer_destroy(&compositor->base); 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) { @@ -435,11 +309,11 @@ android_compositor_destroy(struct weston_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); } @@ -475,12 +349,12 @@ android_compositor_create(struct wl_display *display, int argc, char *argv[], 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 f7b8d68e..42546fff 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -1003,18 +1003,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) @@ -1037,20 +1027,10 @@ 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_create(&ec->base, ec->gbm, gles2_renderer_opaque_attribs, + NULL) < 0) { + gbm_device_destroy(ec->gbm); return -1; } @@ -1969,12 +1949,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(); - destroy_sprites(d); gbm_device_destroy(d->gbm); if (weston_launcher_drm_set_master(&d->base, d->drm.fd, 0) < 0) @@ -2257,12 +2231,9 @@ err_drm_source: wl_event_source_remove(ec->drm_source); wl_list_for_each_safe(weston_seat, next, &ec->base.seat_list, link) evdev_input_destroy(weston_seat); - eglMakeCurrent(ec->base.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, - EGL_NO_CONTEXT); - eglTerminate(ec->base.egl_display); - eglReleaseThread(); - gbm_device_destroy(ec->gbm); err_sprite: + gles2_renderer_destroy(&ec->base); + gbm_device_destroy(ec->gbm); destroy_sprites(ec); err_udev_dev: udev_device_unref(drm_device); diff --git a/src/compositor-rpi.c b/src/compositor-rpi.c index 69f3d591..56119a6d 100644 --- a/src/compositor-rpi.c +++ b/src/compositor-rpi.c @@ -1089,7 +1089,7 @@ rpi_output_create(struct rpi_compositor *compositor) (EGLNativeWindowType)&output->egl_window) < 0) goto out_output; - if (!eglSurfaceAttrib(compositor->base.egl_display, + if (!eglSurfaceAttrib(gles2_renderer_display(&compositor->base), gles2_renderer_output_surface(&output->base), EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) { print_egl_error_state(); @@ -1355,63 +1355,6 @@ evdev_input_destroy(struct weston_seat *seat_base) free(seat); } -static int -rpi_init_egl(struct rpi_compositor *compositor) -{ - EGLint eglmajor, eglminor; - int ret; - EGLint num_config; - - static const EGLint config_attrs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT | - EGL_SWAP_BEHAVIOR_PRESERVED_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 - }; - - 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; - } - - ret = eglInitialize(compositor->base.egl_display, &eglmajor, &eglminor); - if (!ret) { - weston_log("Failed to initialise EGL.\n"); - print_egl_error_state(); - return -1; - } - - ret = eglChooseConfig(compositor->base.egl_display, config_attrs, - &compositor->base.egl_config, 1, &num_config); - if (ret < 0 || num_config != 1) { - weston_log("Failed to find an EGL config (found %d configs).\n", - num_config); - print_egl_error_state(); - return -1; - } - - return 0; -} - -static void -rpi_fini_egl(struct rpi_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 rpi_compositor_destroy(struct weston_compositor *base) { @@ -1424,7 +1367,7 @@ rpi_compositor_destroy(struct weston_compositor *base) /* destroys outputs, too */ weston_compositor_shutdown(&compositor->base); - rpi_fini_egl(compositor); + gles2_renderer_destroy(&compositor->base); tty_destroy(compositor->tty); bcm_host_deinit(); @@ -1506,6 +1449,16 @@ rpi_compositor_create(struct wl_display *display, int argc, char *argv[], struct rpi_compositor *compositor; const char *seat = default_seat; uint32_t key; + static const EGLint config_attrs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT | + EGL_SWAP_BEHAVIOR_PRESERVED_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 + }; weston_log("initializing Raspberry Pi backend\n"); @@ -1556,18 +1509,19 @@ rpi_compositor_create(struct wl_display *display, int argc, char *argv[], */ bcm_host_init(); - if (rpi_init_egl(compositor) < 0) + if (gles2_renderer_create(&compositor->base, EGL_DEFAULT_DISPLAY, + config_attrs, NULL) < 0) goto out_tty; if (rpi_output_create(compositor) < 0) - goto out_egl; + goto out_gles2; evdev_input_create(&compositor->base, compositor->udev, seat); return &compositor->base; -out_egl: - rpi_fini_egl(compositor); +out_gles2: + gles2_renderer_destroy(&compositor->base); out_tty: tty_destroy(compositor->tty); diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c index db977133..1645f7df 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) { @@ -827,7 +792,9 @@ 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_create(&c->base, c->parent.wl_display, + gles2_renderer_alpha_attribs, + NULL) < 0) goto err_display; c->base.destroy = wayland_destroy; @@ -840,9 +807,10 @@ 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 gles2_renderer_init */ + /* requires gles2_renderer_output_state_create called + * by wayland_compositor_create_output */ create_border(c); loop = wl_display_get_event_loop(c->base.wl_display); @@ -852,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 cbb24829..145e4240 100644 --- a/src/compositor-x11.c +++ b/src/compositor-x11.c @@ -307,53 +307,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) @@ -1153,7 +1106,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); @@ -1201,14 +1154,15 @@ 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_create(&c->base, c->dpy, gles2_renderer_opaque_attribs, + NULL) < 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; @@ -1252,8 +1206,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 18265949..9d780cd2 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -286,9 +286,6 @@ struct weston_renderer { struct weston_compositor { struct wl_signal destroy_signal; - EGLDisplay egl_display; - EGLContext egl_context; - EGLConfig egl_config; struct weston_shader texture_shader_rgba; struct weston_shader texture_shader_rgbx; struct weston_shader texture_shader_egl_external; @@ -838,6 +835,14 @@ weston_surface_destroy(struct weston_surface *surface); int weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode); +extern const EGLint gles2_renderer_opaque_attribs[]; +extern const EGLint gles2_renderer_alpha_attribs[]; + +int +gles2_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display, + const EGLint *attribs, const EGLint *visual_id); +EGLDisplay +gles2_renderer_display(struct weston_compositor *ec); int gles2_renderer_output_create(struct weston_output *output, EGLNativeWindowType window); diff --git a/src/gles2-renderer.c b/src/gles2-renderer.c index 2559602b..0f1873df 100644 --- a/src/gles2-renderer.c +++ b/src/gles2-renderer.c @@ -31,22 +31,31 @@ #include "compositor.h" +struct gles2_output_state { + EGLSurface egl_surface; +}; + struct gles2_renderer { struct weston_renderer base; int fragment_shader_debug; -}; -struct gles2_output_state { - EGLSurface egl_surface; + EGLDisplay egl_display; + EGLContext egl_context; + EGLConfig egl_config; }; - 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) { @@ -719,6 +728,7 @@ gles2_renderer_repaint_output(struct weston_output *output, { struct gles2_output_state *go = get_output_state(output); struct weston_compositor *compositor = output->compositor; + struct gles2_renderer *gr = get_renderer(compositor); EGLBoolean ret; static int errored; int32_t width, height, i; @@ -730,8 +740,8 @@ gles2_renderer_repaint_output(struct weston_output *output, glViewport(0, 0, width, height); - ret = eglMakeCurrent(compositor->egl_display, go->egl_surface, - go->egl_surface, compositor->egl_context); + ret = eglMakeCurrent(gr->egl_display, go->egl_surface, + go->egl_surface, gr->egl_context); if (ret == EGL_FALSE) { if (errored) return; @@ -767,7 +777,7 @@ gles2_renderer_repaint_output(struct weston_output *output, wl_signal_emit(&output->frame_signal, output); - ret = eglSwapBuffers(compositor->egl_display, go->egl_surface); + ret = eglSwapBuffers(gr->egl_display, go->egl_surface); if (ret == EGL_FALSE && !errored) { errored = 1; weston_log("Failed in eglSwapBuffers.\n"); @@ -855,12 +865,13 @@ static void gles2_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer) { struct weston_compositor *ec = es->compositor; + struct gles2_renderer *gr = get_renderer(ec); EGLint attribs[3], format; int i, num_planes; if (!buffer) { for (i = 0; i < es->num_images; i++) { - ec->destroy_image(ec->egl_display, es->images[i]); + ec->destroy_image(gr->egl_display, es->images[i]); es->images[i] = NULL; } es->num_images = 0; @@ -882,10 +893,10 @@ gles2_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer) es->shader = &ec->texture_shader_rgbx; else es->shader = &ec->texture_shader_rgba; - } else if (ec->query_buffer(ec->egl_display, buffer, + } else if (ec->query_buffer(gr->egl_display, buffer, EGL_TEXTURE_FORMAT, &format)) { for (i = 0; i < es->num_images; i++) - ec->destroy_image(ec->egl_display, es->images[i]); + ec->destroy_image(gr->egl_display, es->images[i]); es->num_images = 0; es->target = GL_TEXTURE_2D; switch (format) { @@ -919,7 +930,7 @@ gles2_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer) attribs[0] = EGL_WAYLAND_PLANE_WL; attribs[1] = i; attribs[2] = EGL_NONE; - es->images[i] = ec->create_image(ec->egl_display, + es->images[i] = ec->create_image(gr->egl_display, NULL, EGL_WAYLAND_BUFFER_WL, buffer, attribs); @@ -945,12 +956,13 @@ static void gles2_renderer_destroy_surface(struct weston_surface *surface) { struct weston_compositor *ec = surface->compositor; + struct gles2_renderer *gr = get_renderer(ec); int i; glDeleteTextures(surface->num_textures, surface->textures); for (i = 0; i < surface->num_images; i++) - ec->destroy_image(ec->egl_display, surface->images[i]); + ec->destroy_image(gr->egl_display, surface->images[i]); } static const char vertex_shader[] = @@ -1233,14 +1245,15 @@ gles2_renderer_output_create(struct weston_output *output, EGLNativeWindowType window) { struct weston_compositor *ec = output->compositor; + struct gles2_renderer *gr = get_renderer(ec); struct gles2_output_state *go = calloc(1, sizeof *go); if (!go) return -1; go->egl_surface = - eglCreateWindowSurface(ec->egl_display, - ec->egl_config, + eglCreateWindowSurface(gr->egl_display, + gr->egl_config, window, NULL); if (go->egl_surface == EGL_NO_SURFACE) { @@ -1249,7 +1262,7 @@ gles2_renderer_output_create(struct weston_output *output, return -1; } - if (ec->egl_context == NULL) + if (gr->egl_context == NULL) if (gles2_renderer_setup(ec, go->egl_surface) < 0) { free(go); return -1; @@ -1263,9 +1276,10 @@ gles2_renderer_output_create(struct weston_output *output, WL_EXPORT void gles2_renderer_output_destroy(struct weston_output *output) { + struct gles2_renderer *gr = get_renderer(output->compositor); struct gles2_output_state *go = get_output_state(output); - eglDestroySurface(output->compositor->egl_display, go->egl_surface); + eglDestroySurface(gr->egl_display, go->egl_surface); free(go); } @@ -1279,8 +1293,131 @@ gles2_renderer_output_surface(struct weston_output *output) WL_EXPORT void gles2_renderer_destroy(struct weston_compositor *ec) { + struct gles2_renderer *gr = get_renderer(ec); + if (ec->has_bind_display) - ec->unbind_display(ec->egl_display, ec->wl_display); + ec->unbind_display(gr->egl_display, ec->wl_display); + + /* Work around crash in egl_dri2.c's dri2_make_current() - when does this apply? */ + eglMakeCurrent(gr->egl_display, + EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + + eglTerminate(gr->egl_display); + eglReleaseThread(); +} + +static int +egl_choose_config(struct gles2_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 != *visual_id) + continue; + } + + gr->egl_config = configs[i]; + + free(configs); + return 0; + } + +out: + free(configs); + return -1; +} + +WL_EXPORT const EGLint gles2_renderer_opaque_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 +}; + +WL_EXPORT const EGLint gles2_renderer_alpha_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 +}; + +WL_EXPORT int +gles2_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display, + const EGLint *attribs, const EGLint *visual_id) +{ + struct gles2_renderer *gr; + EGLint major, minor; + + gr = calloc(1, sizeof *gr); + + if (gr == NULL) + return -1; + + gr->base.repaint_output = gles2_renderer_repaint_output; + gr->base.flush_damage = gles2_renderer_flush_damage; + gr->base.attach = gles2_renderer_attach; + gr->base.destroy_surface = gles2_renderer_destroy_surface; + + gr->egl_display = eglGetDisplay(display); + if (gr->egl_display == EGL_NO_DISPLAY) { + weston_log("failed to create display\n"); + goto err_egl; + } + + if (!eglInitialize(gr->egl_display, &major, &minor)) { + weston_log("failed to initialize display\n"); + goto err_egl; + } + + if (egl_choose_config(gr, attribs, visual_id) < 0) { + weston_log("failed to choose EGL config\n"); + goto err_egl; + } + + ec->renderer = &gr->base; + + return 0; + +err_egl: + print_egl_error_state(); + free(gr); + return -1; +} + +WL_EXPORT EGLDisplay +gles2_renderer_display(struct weston_compositor *ec) +{ + return get_renderer(ec)->egl_display; } static int @@ -1340,7 +1477,7 @@ fragment_debug_binding(struct wl_seat *seat, uint32_t time, uint32_t key, static int gles2_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface) { - struct gles2_renderer *renderer; + struct gles2_renderer *gr = get_renderer(ec); const char *extensions; EGLBoolean ret; @@ -1349,35 +1486,31 @@ gles2_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface) EGL_NONE }; - renderer = calloc(1, 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(); return -1; } - log_egl_config_info(ec->egl_display, ec->egl_config); + log_egl_config_info(gr->egl_display, gr->egl_config); - ec->egl_context = eglCreateContext(ec->egl_display, ec->egl_config, + gr->egl_context = eglCreateContext(gr->egl_display, gr->egl_config, EGL_NO_CONTEXT, context_attribs); - if (ec->egl_context == NULL) { + if (gr->egl_context == NULL) { weston_log("failed to create context\n"); print_egl_error_state(); return -1; } - ret = eglMakeCurrent(ec->egl_display, egl_surface, - egl_surface, ec->egl_context); + ret = eglMakeCurrent(gr->egl_display, egl_surface, + egl_surface, gr->egl_context); if (ret == EGL_FALSE) { weston_log("Failed to make EGL context current.\n"); print_egl_error_state(); return -1; } - log_egl_gl_info(ec->egl_display); + log_egl_gl_info(gr->egl_display); ec->image_target_texture_2d = (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES"); @@ -1415,7 +1548,7 @@ gles2_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface) ec->has_egl_image_external = 1; extensions = - (const char *) eglQueryString(ec->egl_display, EGL_EXTENSIONS); + (const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS); if (!extensions) { weston_log("Retrieving EGL extension string failed.\n"); return -1; @@ -1424,19 +1557,13 @@ gles2_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface) if (strstr(extensions, "EGL_WL_bind_wayland_display")) ec->has_bind_display = 1; if (ec->has_bind_display) { - ret = ec->bind_display(ec->egl_display, ec->wl_display); + ret = ec->bind_display(gr->egl_display, ec->wl_display); if (!ret) ec->has_bind_display = 0; } glActiveTexture(GL_TEXTURE0); - 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; - if (compile_shaders(ec)) return -1; @@ -1451,5 +1578,6 @@ gles2_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface) weston_log_continue(STAMP_SPACE "EGL Wayland extension: %s\n", ec->has_bind_display ? "yes" : "no"); + return 0; }