On 21 July 2015 at 16:44, Boyan Ding <boyan.j.d...@gmail.com> wrote: > Signed-off-by: Boyan Ding <boyan.j.d...@gmail.com> > --- > configure.ac | 6 + > src/egl/drivers/dri2/Makefile.am | 5 + > src/egl/drivers/dri2/egl_dri2.c | 66 +++- > src/egl/drivers/dri2/egl_dri2.h | 14 +- > src/egl/drivers/dri2/platform_x11.c | 105 ++++++- > src/egl/drivers/dri2/platform_x11_dri3.c | 517 > +++++++++++++++++++++++++++++++ > src/egl/drivers/dri2/platform_x11_dri3.h | 44 +++ > 7 files changed, 748 insertions(+), 9 deletions(-) > create mode 100644 src/egl/drivers/dri2/platform_x11_dri3.c > create mode 100644 src/egl/drivers/dri2/platform_x11_dri3.h > > diff --git a/configure.ac b/configure.ac > index 872f15b..5727db9 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -72,6 +72,7 @@ LIBDRM_INTEL_REQUIRED=2.4.61 > LIBDRM_NVVIEUX_REQUIRED=2.4.33 > LIBDRM_NOUVEAU_REQUIRED=2.4.62 > LIBDRM_FREEDRENO_REQUIRED=2.4.57 > +LIBDRM_EGL_DRI3_REQUIRED=2.4.60 I wouldn't bother with this, but directly bump LIBDRM_REQUIRED.
> DRI2PROTO_REQUIRED=2.6 > DRI3PROTO_REQUIRED=1.0 > PRESENTPROTO_REQUIRED=1.0 > @@ -1771,6 +1772,11 @@ for plat in $egl_platforms; do > > x11) > PKG_CHECK_MODULES([XCB_DRI2], [x11-xcb xcb xcb-dri2 >= > $XCBDRI2_REQUIRED xcb-xfixes]) > + > + PKG_CHECK_EXISTS([libdrm >= LIBDRM_EGL_DRI3_REQUIRED], > [libdrm_render_node=yes], [libdrm_render_node=no]) > + if test "x$libdrm_render_node" = xyes; then > + DEFINES="$DEFINES -DLIBDRM_HAS_RENDERNODE_SUPPORT" > + fi > ;; > > drm) > diff --git a/src/egl/drivers/dri2/Makefile.am > b/src/egl/drivers/dri2/Makefile.am > index 55be4a7..d5b511c 100644 > --- a/src/egl/drivers/dri2/Makefile.am > +++ b/src/egl/drivers/dri2/Makefile.am > @@ -52,6 +52,11 @@ if HAVE_EGL_PLATFORM_X11 > libegl_dri2_la_SOURCES += platform_x11.c > AM_CFLAGS += -DHAVE_X11_PLATFORM > AM_CFLAGS += $(XCB_DRI2_CFLAGS) > +if HAVE_DRI3 > +libegl_dri2_la_SOURCES += \ > + platform_x11_dri3.c \ > + platform_x11_dri3.h > +endif I did reshuffle things recently so I fear that there'll be some conflicts here. > endif > > if HAVE_EGL_PLATFORM_WAYLAND > diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c > index dcce04c..139fe29 100644 > --- a/src/egl/drivers/dri2/egl_dri2.c > +++ b/src/egl/drivers/dri2/egl_dri2.c > @@ -322,6 +322,12 @@ struct dri2_extension_match { > int offset; > }; > > +static struct dri2_extension_match dri3_driver_extensions[] = { > + { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, > + { __DRI_IMAGE_DRIVER, 1, offsetof(struct dri2_egl_display, image_driver) > }, > + { NULL, 0, 0 } > +}; > + > static struct dri2_extension_match dri2_driver_extensions[] = { > { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, > { __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) }, > @@ -464,6 +470,25 @@ dri2_open_driver(_EGLDisplay *disp) > } > > EGLBoolean > +dri2_load_driver_dri3(_EGLDisplay *disp) > +{ > + struct dri2_egl_display *dri2_dpy = disp->DriverData; > + const __DRIextension **extensions; > + > + extensions = dri2_open_driver(disp); > + if (!extensions) > + return EGL_FALSE; > + > + if (!dri2_bind_extensions(dri2_dpy, dri3_driver_extensions, extensions)) { > + dlclose(dri2_dpy->driver); > + return EGL_FALSE; > + } > + dri2_dpy->driver_extensions = extensions; > + > + return EGL_TRUE; > +} > + > +EGLBoolean > dri2_load_driver(_EGLDisplay *disp) > { > struct dri2_egl_display *dri2_dpy = disp->DriverData; > @@ -507,7 +532,9 @@ dri2_setup_screen(_EGLDisplay *disp) > struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); > unsigned int api_mask; > > - if (dri2_dpy->dri2) { > + if (dri2_dpy->image_driver) { > + api_mask = dri2_dpy->image_driver->getAPIMask(dri2_dpy->dri_screen); > + } else if (dri2_dpy->dri2) { > api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen); > } else { > assert(dri2_dpy->swrast); > @@ -527,11 +554,12 @@ dri2_setup_screen(_EGLDisplay *disp) > if (api_mask & (1 << __DRI_API_GLES3)) > disp->ClientAPIs |= EGL_OPENGL_ES3_BIT_KHR; > > - assert(dri2_dpy->dri2 || dri2_dpy->swrast); > + assert(dri2_dpy->image_driver || dri2_dpy->dri2 || dri2_dpy->swrast); > disp->Extensions.KHR_surfaceless_context = EGL_TRUE; > disp->Extensions.MESA_configless_context = EGL_TRUE; > > - if ((dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) || > + if (dri2_dpy->image_driver || > + (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) || > (dri2_dpy->swrast && dri2_dpy->swrast->base.version >= 3)) { > disp->Extensions.KHR_create_context = EGL_TRUE; > > @@ -591,7 +619,14 @@ dri2_create_screen(_EGLDisplay *disp) > > dri2_dpy = disp->DriverData; > > - if (dri2_dpy->dri2) { > + if (dri2_dpy->image_driver) { > + dri2_dpy->dri_screen = > + dri2_dpy->image_driver->createNewScreen2(0, dri2_dpy->fd, > + dri2_dpy->extensions, > + > dri2_dpy->driver_extensions, > + &dri2_dpy->driver_configs, > + disp); > + } else if (dri2_dpy->dri2) { > if (dri2_dpy->dri2->base.version >= 4) { > dri2_dpy->dri_screen = > dri2_dpy->dri2->createNewScreen2(0, dri2_dpy->fd, > @@ -627,7 +662,7 @@ dri2_create_screen(_EGLDisplay *disp) > > extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); > > - if (dri2_dpy->dri2) { > + if (dri2_dpy->image_driver || dri2_dpy->dri2) { > if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions)) > goto cleanup_dri_screen; > } else { > @@ -971,7 +1006,26 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, > _EGLConfig *conf, > else > dri_config = NULL; > > - if (dri2_dpy->dri2) { > + if (dri2_dpy->image_driver) { > + unsigned error; > + unsigned num_attribs = 8; > + uint32_t ctx_attribs[8]; > + > + if (!dri2_fill_context_attribs(dri2_ctx, dri2_dpy, ctx_attribs, > + &num_attribs)) > + goto cleanup; > + > + dri2_ctx->dri_context = > + dri2_dpy->image_driver->createContextAttribs(dri2_dpy->dri_screen, > + api, > + dri_config, > + shared, > + num_attribs / 2, > + ctx_attribs, > + & error, > + dri2_ctx); > + dri2_create_context_attribs_error(error); > + } else if (dri2_dpy->dri2) { > if (dri2_dpy->dri2->base.version >= 3) { > unsigned error; > unsigned num_attribs = 8; > diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h > index 435c670..238e81d 100644 > --- a/src/egl/drivers/dri2/egl_dri2.h > +++ b/src/egl/drivers/dri2/egl_dri2.h > @@ -35,6 +35,10 @@ > #include <xcb/dri2.h> > #include <xcb/xfixes.h> > #include <X11/Xlib-xcb.h> > + > +#ifdef HAVE_DRI3 > +#include "loader_dri3_helper.h" > +#endif > #endif > > #ifdef HAVE_WAYLAND_PLATFORM > @@ -160,6 +164,7 @@ struct dri2_egl_display > const __DRIconfig **driver_configs; > void *driver; > const __DRIcoreExtension *core; > + const __DRIimageDriverExtension *image_driver; > const __DRIdri2Extension *dri2; > const __DRIswrastExtension *swrast; > const __DRI2flushExtension *flush; > @@ -191,6 +196,9 @@ struct dri2_egl_display > #ifdef HAVE_X11_PLATFORM > xcb_connection_t *conn; > int screen; > +#ifdef HAVE_DRI3 > + struct loader_dri3_extensions loader_dri3_ext; > +#endif > #endif > > #ifdef HAVE_WAYLAND_PLATFORM > @@ -204,8 +212,9 @@ struct dri2_egl_display > int formats; > uint32_t capabilities; > int is_render_node; > - int is_different_gpu; > #endif > + > + int is_different_gpu; > }; > > struct dri2_egl_context > @@ -326,6 +335,9 @@ EGLBoolean > dri2_load_driver_swrast(_EGLDisplay *disp); > > EGLBoolean > +dri2_load_driver_dri3(_EGLDisplay *disp); > + > +EGLBoolean > dri2_create_screen(_EGLDisplay *disp); > > __DRIdrawable * > diff --git a/src/egl/drivers/dri2/platform_x11.c > b/src/egl/drivers/dri2/platform_x11.c > index 7e1e9e1..a3bc8e1 100644 > --- a/src/egl/drivers/dri2/platform_x11.c > +++ b/src/egl/drivers/dri2/platform_x11.c > @@ -45,6 +45,10 @@ > #include "egl_dri2_fallbacks.h" > #include "loader.h" > > +#ifdef HAVE_DRI3 > +#include "platform_x11_dri3.h" > +#endif > + > static EGLBoolean > dri2_x11_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, > EGLint interval); > @@ -1204,6 +1208,96 @@ dri2_x11_setup_swap_interval(struct dri2_egl_display > *dri2_dpy) > } > } > > +#ifdef HAVE_DRI3 > +static EGLBoolean > +dri2_initialize_x11_dri3(_EGLDriver *drv, _EGLDisplay *disp) > +{ > + struct dri2_egl_display *dri2_dpy; > + > + dri2_dpy = calloc(1, sizeof *dri2_dpy); > + if (!dri2_dpy) > + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); > + > + disp->DriverData = (void *) dri2_dpy; > + if (disp->PlatformDisplay == NULL) { > + dri2_dpy->conn = xcb_connect(0, &dri2_dpy->screen); > + dri2_dpy->own_device = true; > + } else { > + Display *dpy = disp->PlatformDisplay; > + > + dri2_dpy->conn = XGetXCBConnection(dpy); > + dri2_dpy->screen = DefaultScreen(dpy); > + } > + > + if (xcb_connection_has_error(dri2_dpy->conn)) { > + _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed"); > + goto cleanup_dpy; > + } > + > + if (dri2_dpy->conn) { > + if (!dri3_x11_connect(dri2_dpy)) > + goto cleanup_conn; > + } > + > + if (!dri2_load_driver_dri3(disp)) > + goto cleanup_conn; > + > + dri2_dpy->extensions[0] = &dri3_image_loader_extension.base; > + dri2_dpy->extensions[1] = &use_invalidate.base; > + dri2_dpy->extensions[2] = &image_lookup_extension.base; > + dri2_dpy->extensions[3] = NULL; > + > + dri2_dpy->swap_available = true; > + dri2_dpy->invalidate_available = true; > + > + if (!dri2_create_screen(disp)) > + goto cleanup_fd; > + > + dri2_x11_setup_swap_interval(dri2_dpy); > + > + disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE; > + disp->Extensions.CHROMIUM_sync_control = EGL_TRUE; > + disp->Extensions.EXT_buffer_age = EGL_TRUE; > + > +#ifdef HAVE_WAYLAND_PLATFORM > + disp->Extensions.WL_bind_wayland_display = EGL_TRUE; > +#endif > + > + if (dri2_dpy->conn) { > + if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp)) > + goto cleanup_configs; > + } > + > + dri2_dpy->loader_dri3_ext.core = dri2_dpy->core; > + dri2_dpy->loader_dri3_ext.image_driver = dri2_dpy->image_driver; > + dri2_dpy->loader_dri3_ext.flush = dri2_dpy->flush; > + dri2_dpy->loader_dri3_ext.tex_buffer = dri2_dpy->tex_buffer; > + dri2_dpy->loader_dri3_ext.image = dri2_dpy->image; > + dri2_dpy->loader_dri3_ext.config = dri2_dpy->config; > + > + /* Fill vtbl last to prevent accidentally calling virtual function during > + * initialization. > + */ > + dri2_dpy->vtbl = &dri3_x11_display_vtbl; > + > + return EGL_TRUE; > + > + cleanup_configs: > + _eglCleanupDisplay(disp); > + dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); > + dlclose(dri2_dpy->driver); > + cleanup_fd: > + close(dri2_dpy->fd); > + cleanup_conn: > + if (disp->PlatformDisplay == NULL) > + xcb_disconnect(dri2_dpy->conn); > + cleanup_dpy: > + free(dri2_dpy); > + > + return EGL_FALSE; > +} > +#endif > + > static EGLBoolean > dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp) > { > @@ -1323,9 +1417,16 @@ dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp) > int x11_dri2_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL); > > if (x11_dri2_accel) { > - if (!dri2_initialize_x11_dri2(drv, disp)) { > - initialized = dri2_initialize_x11_swrast(drv, disp); > +#ifdef HAVE_DRI3 > + if (getenv("LIBGL_DRI3_DISABLE") != NULL || > + !dri2_initialize_x11_dri3(drv, disp)) { > +#endif > + if (!dri2_initialize_x11_dri2(drv, disp)) { > + initialized = dri2_initialize_x11_swrast(drv, disp); > + } > +#ifdef HAVE_DRI3 > } > +#endif > } else { > initialized = dri2_initialize_x11_swrast(drv, disp); > } > diff --git a/src/egl/drivers/dri2/platform_x11_dri3.c > b/src/egl/drivers/dri2/platform_x11_dri3.c > new file mode 100644 > index 0000000..b570a57 > --- /dev/null > +++ b/src/egl/drivers/dri2/platform_x11_dri3.c > @@ -0,0 +1,517 @@ > +/* > + * Copyright © 2015 Boyan Ding > + * > + * Permission to use, copy, modify, distribute, and sell this software and > its > + * documentation for any purpose is hereby granted without fee, provided that > + * the above copyright notice appear in all copies and that both that > copyright > + * notice and this permission notice appear in supporting documentation, and > + * that the name of the copyright holders not be used in advertising or > + * publicity pertaining to distribution of the software without specific, > + * written prior permission. The copyright holders make no representations > + * about the suitability of this software for any purpose. It is provided > "as > + * is" without express or implied warranty. > + * > + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS > SOFTWARE, > + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO > + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR > + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF > USE, > + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER > + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR > PERFORMANCE > + * OF THIS SOFTWARE. > + */ > + > +#include <stdbool.h> > +#include <stdlib.h> > +#include <string.h> > +#include <unistd.h> > + > +#include <xcb/xcb.h> > +#include <xcb/dri3.h> > +#include <xcb/present.h> > + > +#ifdef HAVE_LIBDRM While correct, we can drop the guard as we require libdrm. > +#include <xf86drm.h> > +#endif > + > +#include "egl_dri2.h" > +#include "egl_dri2_fallbacks.h" > +#include "platform_x11_dri3.h" > + > +#include "loader.h" > +#include "loader_dri3_helper.h" > + > +static int > +egl_dri3_get_swap_interval(struct loader_dri3_drawable *draw) > +{ > + struct dri3_egl_surface *dri3_surf = draw->priv; > + > + return dri3_surf->base.SwapInterval; > +} > + > +static int > +egl_dri3_clamp_swap_interval(struct loader_dri3_drawable *draw, int interval) > +{ > + struct dri3_egl_surface *dri3_surf = draw->priv; > + > + if (interval > dri3_surf->base.Config->MaxSwapInterval) > + interval = dri3_surf->base.Config->MaxSwapInterval; > + else if (interval < dri3_surf->base.Config->MinSwapInterval) > + interval = dri3_surf->base.Config->MinSwapInterval; > + > + return interval; > +} > + > +static void > +egl_dri3_set_swap_interval(struct loader_dri3_drawable *draw, int interval) > +{ > + struct dri3_egl_surface *dri3_surf = draw->priv; > + > + dri3_surf->base.SwapInterval = interval; > +} > + > +static void > +egl_dri3_set_drawable_size(struct loader_dri3_drawable *draw, > + int width, int height) > +{ > + struct dri3_egl_surface *dri3_surf = draw->priv; > + > + dri3_surf->base.Width = width; > + dri3_surf->base.Height = height; > +} > + > +static int > +egl_dri3_get_width(struct loader_dri3_drawable *draw) > +{ > + struct dri3_egl_surface *dri3_surf = draw->priv; > + > + return dri3_surf->base.Width; > +} > + > +static int > +egl_dri3_get_height(struct loader_dri3_drawable *draw) > +{ > + struct dri3_egl_surface *dri3_surf = draw->priv; > + > + return dri3_surf->base.Height; > +} > + > +static bool > +egl_dri3_is_different_gpu(struct loader_dri3_drawable *draw) > +{ > + struct dri3_egl_surface *dri3_surf = draw->priv; > + struct dri2_egl_display *dri2_dpy = > + dri2_egl_display(dri3_surf->base.Resource.Display); > + > + return dri2_dpy->is_different_gpu; > +} > + > +static bool > +egl_dri3_in_current_context(struct loader_dri3_drawable *draw) > +{ > + struct dri3_egl_surface *dri3_surf = draw->priv; > + _EGLContext *ctx = _eglGetCurrentContext(); > + > + return ctx->Resource.Display == dri3_surf->base.Resource.Display; > +} > + > +static __DRIcontext * > +egl_dri3_get_dri_context(struct loader_dri3_drawable *draw) > +{ > + _EGLContext *ctx = _eglGetCurrentContext(); > + struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); > + > + return dri2_ctx->dri_context; > +} > + > +static __DRIscreen * > +egl_dri3_get_dri_screen(struct loader_dri3_drawable *draw) > +{ > + struct dri3_egl_surface *dri3_surf = draw->priv; > + struct dri2_egl_display *dri2_dpy = > + dri2_egl_display(dri3_surf->base.Resource.Display); > + > + return dri2_dpy->dri_screen; > +} > + > +static void > +egl_dri3_flush_drawable(struct loader_dri3_drawable *draw, unsigned flags) > +{ > + struct dri3_egl_surface *dri3_surf = draw->priv; > + _EGLDisplay *disp = dri3_surf->base.Resource.Display; > + > + dri2_flush_drawable_for_swapbuffers(disp, &dri3_surf->base); > +} > + > +static struct loader_dri3_vtable egl_dri3_vtable = { > + .get_swap_interval = egl_dri3_get_swap_interval, > + .clamp_swap_interval = egl_dri3_clamp_swap_interval, > + .set_swap_interval = egl_dri3_set_swap_interval, > + .set_drawable_size = egl_dri3_set_drawable_size, > + .get_width = egl_dri3_get_width, > + .get_height = egl_dri3_get_height, > + .is_different_gpu = egl_dri3_is_different_gpu, > + .in_current_context = egl_dri3_in_current_context, > + .get_dri_context = egl_dri3_get_dri_context, > + .get_dri_screen = egl_dri3_get_dri_screen, > + .flush_drawable = egl_dri3_flush_drawable, > + .show_fps = NULL, > +}; > + > +static EGLBoolean > +dri3_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) > +{ > + struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf); > + > + (void) drv; > + > + if (!_eglPutSurface(surf)) > + return EGL_TRUE; > + > + loader_dri3_destroy_drawable(dri3_surf->loader_drawable); > + > + free(surf); > + > + return EGL_TRUE; > +} > + > +static EGLBoolean > +dri3_set_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, > + EGLint interval) > +{ > + struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf); > + > + loader_dri3_set_swap_interval(dri3_surf->loader_drawable, interval); > + > + return EGL_TRUE; > +} > + > +static xcb_screen_t * > +get_xcb_screen(xcb_screen_iterator_t iter, int screen) > +{ > + for (; iter.rem; --screen, xcb_screen_next(&iter)) > + if (screen == 0) > + return iter.data; > + > + return NULL; > +} > + > +static _EGLSurface * > +dri3_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, > + _EGLConfig *conf, void *native_surface, > + const EGLint *attrib_list) > +{ > + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); > + struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); > + struct dri3_egl_surface *dri3_surf; > + xcb_drawable_t drawable; > + xcb_screen_iterator_t s; > + xcb_screen_t *screen; > + > + STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface)); > + drawable = (uintptr_t) native_surface; > + > + (void) drv; > + > + dri3_surf = calloc(1, sizeof *dri3_surf); > + if (!dri3_surf) { > + _eglError(EGL_BAD_ALLOC, "dri3_create_surface"); > + return NULL; > + } > + > + if (!_eglInitSurface(&dri3_surf->base, disp, type, conf, attrib_list)) > + goto cleanup_surf; > + > + if (type == EGL_PBUFFER_BIT) { > + s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); > + screen = get_xcb_screen(s, dri2_dpy->screen); > + if (!screen) { > + _eglError(EGL_BAD_NATIVE_WINDOW, "dri3_create_surface"); > + goto cleanup_surf; > + } > + > + drawable = xcb_generate_id(dri2_dpy->conn); > + xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize, > + drawable, screen->root, > + dri3_surf->base.Width, dri3_surf->base.Height); > + } > + > + dri3_surf->loader_drawable = > + loader_dri3_create_drawable(dri2_dpy->conn, drawable, > + dri2_dpy->dri_screen, > + type == EGL_WINDOW_BIT ? > + dri2_conf->dri_double_config : > + dri2_conf->dri_single_config, > + &dri2_dpy->loader_dri3_ext, > + &egl_dri3_vtable, > + dri3_surf); > + if (!dri3_surf->loader_drawable) { > + _eglError(EGL_BAD_ALLOC, "dri3_surface_create"); > + goto cleanup_pixmap; > + } > + > + return &dri3_surf->base; > + > + cleanup_pixmap: > + if (type == EGL_PBUFFER_BIT) > + xcb_free_pixmap(dri2_dpy->conn, drawable); > + cleanup_surf: > + free(dri3_surf); > + > + return NULL; > +} > + > +/** > + * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). > + */ > +static _EGLSurface * > +dri3_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, > + _EGLConfig *conf, void *native_window, > + const EGLint *attrib_list) > +{ > + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); > + _EGLSurface *surf; > + > + surf = dri3_create_surface(drv, disp, EGL_WINDOW_BIT, conf, > + native_window, attrib_list); > + if (surf != NULL) > + dri3_set_swap_interval(drv, disp, surf, > dri2_dpy->default_swap_interval); > + > + return surf; > +} > + > +static _EGLSurface * > +dri3_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp, > + _EGLConfig *conf, void *native_pixmap, > + const EGLint *attrib_list) > +{ > + return dri3_create_surface(drv, disp, EGL_PIXMAP_BIT, conf, > + native_pixmap, attrib_list); > +} > + > +static _EGLSurface * > +dri3_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp, > + _EGLConfig *conf, const EGLint *attrib_list) > +{ > + return dri3_create_surface(drv, disp, EGL_PBUFFER_BIT, conf, > + XCB_WINDOW_NONE, attrib_list); > +} > + > +static EGLBoolean > +dri3_get_sync_values(_EGLDisplay *display, _EGLSurface *surface, > + EGLuint64KHR *ust, EGLuint64KHR *msc, > + EGLuint64KHR *sbc) > +{ > + struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surface); > + > + return loader_dri3_wait_for_msc(dri3_surf->loader_drawable, 0, 0, 0, > + ust, msc, sbc) ? EGL_TRUE : EGL_FALSE; > +} > + > +/** > + * Called by the driver when it needs to update the real front buffer with > the > + * contents of its fake front buffer. > + */ > +static void > +dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate) > +{ > + /* FIXME: Does EGL support front buffer rendering at all? */ > + _eglLog(_EGL_WARNING, "FIXME: egl/x11 doesn't support front buffer > rendering."); I believe that EGL does not support front buffer rendering. Although I could be wrong. > + (void) driDrawable; > + (void) loaderPrivate; > +} > + > +const __DRIimageLoaderExtension dri3_image_loader_extension = { > + .base = { __DRI_IMAGE_LOADER, 1 }, > + > + .getBuffers = loader_dri3_get_buffers, > + .flushFrontBuffer = dri3_flush_front_buffer, > +}; > + > +static EGLBoolean > +dri3_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) > +{ > + struct dri3_egl_surface *dri3_surf = dri3_egl_surface(draw); > + > + /* No-op for a pixmap or pbuffer surface */ > + if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT) > + return 0; > + > + return loader_dri3_swap_buffers_msc(dri3_surf->loader_drawable, > + 0, 0, 0, 0, > + draw->SwapBehavior == > EGL_BUFFER_PRESERVED) != -1; > +} > + > +static EGLBoolean > +dri3_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, > + void *native_pixmap_target) > +{ > + struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf); > + xcb_pixmap_t target; > + > + STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_pixmap_target)); > + target = (uintptr_t) native_pixmap_target; > + > + loader_dri3_copy_drawable(dri3_surf->loader_drawable, target, > + dri3_surf->loader_drawable->drawable); > + > + return EGL_TRUE; > +} > + > +static int > +dri3_query_buffer_age(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) > +{ > + struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf); > + > + return loader_dri3_query_buffer_age(dri3_surf->loader_drawable); > +} > + > +static int > +dri3_authenticate(_EGLDisplay *disp, uint32_t id) > +{ > + /* If the device is render node, authentication is not needed, if it is > + * master, authentication won't succeed anyway. > + */ > + _eglLog(_EGL_WARNING, "authentication shouldn't be called on dri3"); > + Last time I've looked (a little while ago) one can just omit this function, and set the vtbl entry to NULL. > + return 0; > +} > + > +static __DRIdrawable * > +dri3_get_dri_drawable(_EGLSurface *surf) > +{ > + struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf); > + > + return dri3_surf->loader_drawable->dri_drawable; > +} > + > +struct dri2_egl_display_vtbl dri3_x11_display_vtbl = { > + .authenticate = dri3_authenticate, > + .create_window_surface = dri3_create_window_surface, > + .create_pixmap_surface = dri3_create_pixmap_surface, > + .create_pbuffer_surface = dri3_create_pbuffer_surface, > + .destroy_surface = dri3_destroy_surface, > + .create_image = dri2_create_image_khr, > + .swap_interval = dri3_set_swap_interval, > + .swap_buffers = dri3_swap_buffers, > + .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage, > + .swap_buffers_region = dri2_fallback_swap_buffers_region, > + .post_sub_buffer = dri2_fallback_post_sub_buffer, > + .copy_buffers = dri3_copy_buffers, > + .query_buffer_age = dri3_query_buffer_age, > + .create_wayland_buffer_from_image = > dri2_fallback_create_wayland_buffer_from_image, > + .get_sync_values = dri3_get_sync_values, > + .get_dri_drawable = dri3_get_dri_drawable, > +}; > + > +static char * > +dri3_get_device_name(int fd) > +{ > + char *ret = NULL; > + > +#ifdef LIBDRM_HAS_RENDERNODE_SUPPORT > + ret = drmGetRenderDeviceNameFromFd(fd); > +#endif > + if (ret) > + return ret; > + > + /* For dri3, render node support is required for WL_bind_wayland_display. > + * In order not to regress on older systems without kernel or libdrm > + * support, fall back to dri2. User can override it with environment > + * variable if they don't need to use that extension. > + */ Can we just disable the extension, if the above call fails ? > + if (getenv("EGL_FORCE_DRI3") == NULL) { > + _eglLog(_EGL_WARNING, "Render node support not available, falling back > to dri2"); > + _eglLog(_EGL_WARNING, "If you want to force dri3, set EGL_FORCE_DRI3 > environment variable"); > + } else > + ret = loader_get_device_name_for_fd(fd); > + > + return ret; > +} > + > +EGLBoolean > +dri3_x11_connect(struct dri2_egl_display *dri2_dpy) > +{ > + xcb_dri3_query_version_reply_t *dri3_query; > + xcb_dri3_query_version_cookie_t dri3_query_cookie; > + xcb_present_query_version_reply_t *present_query; > + xcb_present_query_version_cookie_t present_query_cookie; > + xcb_generic_error_t *error; > + xcb_screen_iterator_t s; > + xcb_screen_t *screen; > + const xcb_query_extension_reply_t *extension; > + > + xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri3_id); > + xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_present_id); > + > + extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri3_id); > + if (!(extension && extension->present)) > + return EGL_FALSE; > + > + extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_present_id); > + if (!(extension && extension->present)) > + return EGL_FALSE; > + > + dri3_query_cookie = xcb_dri3_query_version(dri2_dpy->conn, > + XCB_DRI3_MAJOR_VERSION, > + XCB_DRI3_MINOR_VERSION); > + > + present_query_cookie = xcb_present_query_version(dri2_dpy->conn, > + > XCB_PRESENT_MAJOR_VERSION, > + > XCB_PRESENT_MINOR_VERSION); > + > + dri3_query = > + xcb_dri3_query_version_reply(dri2_dpy->conn, dri3_query_cookie, > &error); > + if (dri3_query == NULL || error != NULL) { > + _eglLog(_EGL_WARNING, "DRI2: failed to query dri3 version"); > + free(dri3_query); > + free(error); > + return EGL_FALSE; > + } > + free(dri3_query); > + > + present_query = > + xcb_present_query_version_reply(dri2_dpy->conn, > + present_query_cookie, &error); > + if (present_query == NULL || error != NULL) { > + _eglLog(_EGL_WARNING, "DRI2: failed to query Present version"); > + free(present_query); > + free(error); > + return EGL_FALSE; > + } > + free(present_query); > + > + s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); > + screen = get_xcb_screen(s, dri2_dpy->screen); > + if (!screen) { > + _eglError(EGL_BAD_NATIVE_WINDOW, "dri3_x11_connect"); > + return EGL_FALSE; > + } > + > + dri2_dpy->fd = loader_dri3_open(dri2_dpy->conn, screen->root, 0); > + if (dri2_dpy->fd < 0) { > + int conn_error = xcb_connection_has_error(dri2_dpy->conn); > + _eglLog(_EGL_WARNING, "DRI2: Screen seem not DRI3 capable"); > + > + if (conn_error) > + _eglLog(_EGL_WARNING, "DRI2: Failed to initialize DRI3"); > + > + return EGL_FALSE; > + } > + > + dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd, > &dri2_dpy->is_different_gpu); > + > + dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd, 0); > + if (!dri2_dpy->driver_name) { > + _eglLog(_EGL_WARNING, "DRI2: No driver found"); > + close(dri2_dpy->fd); > + return EGL_FALSE; > + } > + > + dri2_dpy->device_name = dri3_get_device_name(dri2_dpy->fd); > + if (!dri2_dpy->device_name) { > + close(dri2_dpy->fd); > + return EGL_FALSE; > + } > + > + return EGL_TRUE; > +} > diff --git a/src/egl/drivers/dri2/platform_x11_dri3.h > b/src/egl/drivers/dri2/platform_x11_dri3.h > new file mode 100644 > index 0000000..b9d0f3d > --- /dev/null > +++ b/src/egl/drivers/dri2/platform_x11_dri3.h > @@ -0,0 +1,44 @@ > +/* > + * Copyright © 2015 Boyan Ding > + * > + * Permission to use, copy, modify, distribute, and sell this software and > its > + * documentation for any purpose is hereby granted without fee, provided that > + * the above copyright notice appear in all copies and that both that > copyright > + * notice and this permission notice appear in supporting documentation, and > + * that the name of the copyright holders not be used in advertising or > + * publicity pertaining to distribution of the software without specific, > + * written prior permission. The copyright holders make no representations > + * about the suitability of this software for any purpose. It is provided > "as > + * is" without express or implied warranty. > + * > + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS > SOFTWARE, > + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO > + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR > + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF > USE, > + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER > + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR > PERFORMANCE > + * OF THIS SOFTWARE. > + */ > + > +#ifndef EGL_X11_DRI3_INCLUDED > +#define EGL_X11_DRI3_INCLUDED > + > +#include <GL/gl.h> This include feels a bit odd. We don't seem to (directly) require it by of the following code. > +#include <GL/internal/dri_interface.h> > + > +#include "egl_dri2.h" > + > +_EGL_DRIVER_TYPECAST(dri3_egl_surface, _EGLSurface, obj) > + > +struct dri3_egl_surface { > + _EGLSurface base; > + struct loader_dri3_drawable *loader_drawable; > +}; > + > +extern const __DRIimageLoaderExtension dri3_image_loader_extension; > +extern struct dri2_egl_display_vtbl dri3_x11_display_vtbl; > + > +EGLBoolean > +dri3_x11_connect(struct dri2_egl_display *dri2_dpy); > + > +#endif > -- > 2.4.4 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev