[Mesa-dev] [RFC] egl: Add DRI3 support to the EGL backend.

Joonas Lahtinen joonas.lahtinen at linux.intel.com
Tue Oct 28 02:19:08 PDT 2014


Hi,

On pe, 2014-10-24 at 17:37 +0000, Emil Velikov wrote:
> Hi Joonas,
> 
> On 22/10/14 18:17, Joonas Lahtinen wrote:
> > Hi,
> > 
> > This patch introduced DRI3 support to the EGL backend.
> > 
> > Patch is on top of current master. With the patch you can observe
> > reduced CPU stress when many glViewport calls are made.
> > 
> > Notice that the DRI3 extension is only exposed if the DRI3 interface is
> > found working too instead of just existing. So you need to enable DRI3
> > from all three; Mesa, X driver and X server, to get the benefit.
> > 
> It seems that you introduce yet another dri extension
> (DRIdri3Extension) which afaict should not be needed ?
> 
> Am I missing something here or did you get carried away by looking at
> __DRIcoreExtension, __DRIdri2Extension and __DRIswrastExtension :P
> 

The DRI3 (just like the USE_INVALIDATE extension) extension is needed
for the drivers to know that they do not need to invalidate buffers on
each glViewport call.

One could use USE_INVALIDATE extension for same functionality, but I see
it would not be very good idea as the naming vs. context would be
confusing.

DRI3 is exposed dynamically depending on if DRI3 is usable or not. The
USE_INVALIDATE is exposed as long as GLX is used. So that also makes
them bit different (in logic too, not just naming).

Regards, Joonas

> Thanks
> Emil
> 
> > Regards, Joonas
> > 
> > PS. Will be traveling over the weekend, so will react to comments on
> > Monday.
> > 
> > From c945e777e0aaf77a5ec450cdec1cf4db89ef0c8d Mon Sep 17 00:00:00 2001
> > From: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
> > Date: Wed, 22 Oct 2014 21:05:31 +0300
> > Subject: [PATCH] egl: Add DRI3 support to the EGL backend.
> > 
> > DRI3 support is needed to avoid excess buffer invalidations, because
> > the XCB interface doesn't supply that information through DRI2.
> > 
> > Signed-off-by: Daniel van der Wath <danielx.j.van.der.wath at intel.com>
> > Signed-off-by: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
> > ---
> >  configure.ac                            |    4 +
> >  include/GL/internal/dri_interface.h     |    8 +
> >  src/egl/drivers/dri2/egl_dri2.c         |    9 +
> >  src/egl/drivers/dri2/egl_dri2.h         |   39 +++-
> >  src/egl/drivers/dri2/platform_x11.c     |  340 ++++++++++++++++++++++++++++++-
> >  src/egl/main/Makefile.am                |    4 +
> >  src/mesa/drivers/dri/common/dri_util.c  |    2 +
> >  src/mesa/drivers/dri/common/dri_util.h  |    1 +
> >  src/mesa/drivers/dri/i965/brw_context.c |   12 +-
> >  9 files changed, 406 insertions(+), 13 deletions(-)
> > 
> > diff --git a/configure.ac b/configure.ac
> > index 0ed9325..308fddf 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -43,6 +43,7 @@ VDPAU_REQUIRED=0.4.1
> >  WAYLAND_REQUIRED=1.2.0
> >  XCB_REQUIRED=1.9.3
> >  XCBDRI2_REQUIRED=1.8
> > +XCBDRI3_REQUIRED=1.8
> >  XCBGLX_REQUIRED=1.8.1
> >  XSHMFENCE_REQUIRED=1.1
> >  XVMC_REQUIRED=1.0.6
> > @@ -1557,6 +1558,9 @@ for plat in $egl_platforms; do
> >  
> >  	x11)
> >  		PKG_CHECK_MODULES([XCB_DRI2], [x11-xcb xcb xcb-dri2 >= $XCBDRI2_REQUIRED xcb-xfixes])
> > +		if test x"$enable_dri3" = "xyes"; then
> > +			PKG_CHECK_MODULES([XCB_DRI3], [xcb-dri3 >= $XCBDRI3_REQUIRED xcb-present])
> > +		fi
> >  		;;
> >  
> >  	drm)
> > diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
> > index 8c5ceb9..3bd9d18 100644
> > --- a/include/GL/internal/dri_interface.h
> > +++ b/include/GL/internal/dri_interface.h
> > @@ -83,6 +83,7 @@ typedef struct __DRIswrastExtensionRec		__DRIswrastExtension;
> >  typedef struct __DRIbufferRec			__DRIbuffer;
> >  typedef struct __DRIdri2ExtensionRec		__DRIdri2Extension;
> >  typedef struct __DRIdri2LoaderExtensionRec	__DRIdri2LoaderExtension;
> > +typedef struct __DRIdri3ExtensionRec		__DRIdri3Extension;
> >  typedef struct __DRI2flushExtensionRec	__DRI2flushExtension;
> >  typedef struct __DRI2throttleExtensionRec	__DRI2throttleExtension;
> >  
> > @@ -999,6 +1000,13 @@ struct __DRIdri2ExtensionRec {
> >     __DRIcreateNewScreen2Func            createNewScreen2;
> >  };
> >  
> > +#define __DRI_DRI3 "DRI_DRI3"
> > +#define __DRI_DRI3_VERSION 1
> > +
> > +struct __DRIdri3ExtensionRec {
> > +   __DRIextension base;
> > +};
> > +
> >  
> >  /**
> >   * This extension provides functionality to enable various EGLImage
> > diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
> > index 20a7243..6024cb3 100644
> > --- a/src/egl/drivers/dri2/egl_dri2.c
> > +++ b/src/egl/drivers/dri2/egl_dri2.c
> > @@ -55,6 +55,12 @@ const __DRIuseInvalidateExtension use_invalidate = {
> >     .base = { __DRI_USE_INVALIDATE, 1 }
> >  };
> >  
> > +#ifdef HAVE_DRI3
> > +const __DRIdri3Extension dri3_extension = {
> > +   .base = { __DRI_DRI3, 1 }
> > +};
> > +#endif
> > +
> >  EGLint dri2_to_egl_attribute_map[] = {
> >     0,
> >     EGL_BUFFER_SIZE,		/* __DRI_ATTRIB_BUFFER_SIZE */
> > @@ -600,6 +606,9 @@ dri2_create_screen(_EGLDisplay *disp)
> >  	 if (strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0) {
> >  	    dri2_dpy->config = (__DRI2configQueryExtension *) extensions[i];
> >  	 }
> > +         if (strcmp(extensions[i]->name, __DRI_DRI3) == 0) {
> > +            dri2_dpy->dri3 = (__DRIdri3Extension *) extensions[i];
> > +         }
> >        }
> >     } else {
> >        assert(dri2_dpy->swrast);
> > diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
> > index 52f05fb..d8713df 100644
> > --- a/src/egl/drivers/dri2/egl_dri2.h
> > +++ b/src/egl/drivers/dri2/egl_dri2.h
> > @@ -35,6 +35,11 @@
> >  #include <X11/Xlib-xcb.h>
> >  #endif
> >  
> > +#ifdef HAVE_DRI3
> > +#include <xcb/dri3.h>
> > +#include <xcb/present.h>
> > +#endif
> > +
> >  #ifdef HAVE_WAYLAND_PLATFORM
> >  #include <wayland-client.h>
> >  #include "wayland-egl-priv.h"
> > @@ -74,6 +79,7 @@
> >  #include "eglimage.h"
> >  
> >  #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
> > +#define DRI2_EGL_SURFACE_NUM_BUFFERS 5
> >  
> >  struct wl_buffer;
> >  
> > @@ -150,12 +156,17 @@ struct dri2_egl_display
> >  
> >     int                       dri2_major;
> >     int                       dri2_minor;
> > +#ifdef HAVE_DRI3
> > +   int                       dri3_major;
> > +   int                       dri3_minor;
> > +#endif
> >     __DRIscreen              *dri_screen;
> >     int                       own_dri_screen;
> >     const __DRIconfig       **driver_configs;
> >     void                     *driver;
> >     const __DRIcoreExtension       *core;
> >     const __DRIdri2Extension       *dri2;
> > +   const __DRIdri3Extension       *dri3;
> >     const __DRIswrastExtension     *swrast;
> >     const __DRI2flushExtension     *flush;
> >     const __DRItexBufferExtension  *tex_buffer;
> > @@ -163,6 +174,7 @@ struct dri2_egl_display
> >     const __DRIrobustnessExtension *robustness;
> >     const __DRI2configQueryExtension *config;
> >     int                       fd;
> > +   int                       dri3_present_and_working;
> >  
> >     int                       own_device;
> >     int                       swap_available;
> > @@ -218,7 +230,7 @@ struct dri2_egl_surface
> >  {
> >     _EGLSurface          base;
> >     __DRIdrawable       *dri_drawable;
> > -   __DRIbuffer          buffers[5];
> > +   __DRIbuffer          buffers[DRI2_EGL_SURFACE_NUM_BUFFERS];
> >     int                  buffer_count;
> >     int                  have_fake_front;
> >  
> > @@ -229,6 +241,28 @@ struct dri2_egl_surface
> >     int                  bytes_per_pixel;
> >     xcb_gcontext_t       gc;
> >     xcb_gcontext_t       swapgc;
> > +#ifdef HAVE_DRI3
> > +   xcb_special_event_t *special_event;
> > +   xcb_present_event_t eid;
> > +   uint32_t *stamp;
> > +   uint8_t is_pixmap;
> > +   uint8_t flipping;
> > +
> > +   /* SBC numbers are tracked by using the serial numbers
> > +    * in the present request and complete events
> > +    */
> > +   uint64_t send_sbc;
> > +   uint64_t recv_sbc;
> > +
> > +   /* Last received UST/MSC values */
> > +   uint64_t ust, msc;
> > +
> > +   int num_back;
> > +
> > +   /* Serial numbers for tracking wait_for_msc events */
> > +   uint32_t send_msc_serial;
> > +   uint32_t recv_msc_serial;
> > +#endif
> >  #endif
> >  
> >  #ifdef HAVE_WAYLAND_PLATFORM
> > @@ -293,6 +327,9 @@ _EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj)
> >  
> >  extern const __DRIimageLookupExtension image_lookup_extension;
> >  extern const __DRIuseInvalidateExtension use_invalidate;
> > +#ifdef HAVE_DRI3
> > +extern const __DRIdri3Extension dri3_extension;
> > +#endif
> >  
> >  EGLBoolean
> >  dri2_load_driver(_EGLDisplay *disp);
> > diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c
> > index f8c4b70..3bf0c96 100644
> > --- a/src/egl/drivers/dri2/platform_x11.c
> > +++ b/src/egl/drivers/dri2/platform_x11.c
> > @@ -188,6 +188,240 @@ get_xcb_screen(xcb_screen_iterator_t iter, int screen)
> >      return NULL;
> >  }
> >  
> > +#ifdef HAVE_DRI3
> > +/** dri3_open
> > + *
> > + * Wrapper around xcb_dri3_open
> > + */
> > +static int
> > +dri3_open(struct dri2_egl_display *dri2_dpy,
> > +          Window root,
> > +          uint32_t provider)
> > +{
> > +   xcb_dri3_open_cookie_t       cookie;
> > +   xcb_dri3_open_reply_t        *reply;
> > +   xcb_connection_t             *c = dri2_dpy->conn;
> > +   int                          fd;
> > +
> > +   cookie = xcb_dri3_open(c,
> > +                          root,
> > +                          provider);
> > +
> > +   reply = xcb_dri3_open_reply(c, cookie, NULL);
> > +   if (!reply)
> > +      return -1;
> > +
> > +   if (reply->nfd != 1) {
> > +      free(reply);
> > +      return -1;
> > +   }
> > +
> > +   fd = xcb_dri3_open_reply_fds(c, reply)[0];
> > +
> > +   fcntl(fd, F_SETFD, FD_CLOEXEC);
> > +   return fd;
> > +}
> > +
> > +/* from glx. Called by the XCB_PRESENT_COMPLETE_NOTIFY case.
> > + */
> > +static void
> > +dri3_update_num_back(struct dri2_egl_surface *priv)
> > +{
> > +   priv->num_back = 1;
> > +   if (priv->flipping)
> > +      priv->num_back++;
> > +   if (priv->base.SwapInterval == 0)
> > +      priv->num_back++;
> > +}
> > +
> > +/** dri3_free_render_buffer
> > + *
> > + * In the glx version there's some more clean up, but here we can just call releaseBuffer().
> > + */
> > +static void
> > +dri3_free_render_buffer(struct dri2_egl_surface *pdraw, __DRIbuffer *buffer)
> > +{
> > +   struct dri2_egl_display *dri2_dpy = dri2_egl_display(pdraw->base.Resource.Display);
> > +
> > +   (*dri2_dpy->dri2->releaseBuffer)(dri2_dpy->dri_screen, buffer);
> > +}
> > +
> > +/*
> > + * Process one Present event
> > + */
> > +static void
> > +dri3_handle_present_event(struct dri2_egl_surface *priv, xcb_present_generic_event_t *ge)
> > +{
> > +   switch (ge->evtype) {
> > +   case XCB_PRESENT_CONFIGURE_NOTIFY: {
> > +      xcb_present_configure_notify_event_t *ce = (void *) ge;
> > +
> > +      priv->base.Width = ce->width;
> > +      priv->base.Height = ce->height;
> > +      break;
> > +   }
> > +   case XCB_PRESENT_COMPLETE_NOTIFY: {
> > +      xcb_present_complete_notify_event_t *ce = (void *) ge;
> > +
> > +      /* Compute the processed SBC number from the received 32-bit serial number merged
> > +       * with the upper 32-bits of the sent 64-bit serial number while checking for
> > +       * wrap
> > +       */
> > +      if (ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP) {
> > +         priv->recv_sbc = (priv->send_sbc & 0xffffffff00000000LL) | ce->serial;
> > +         if (priv->recv_sbc > priv->send_sbc)
> > +            priv->recv_sbc -= 0x100000000;
> > +         switch (ce->mode) {
> > +         case XCB_PRESENT_COMPLETE_MODE_FLIP:
> > +            priv->flipping = true;
> > +            break;
> > +         case XCB_PRESENT_COMPLETE_MODE_COPY:
> > +            priv->flipping = false;
> > +            break;
> > +         }
> > +         dri3_update_num_back(priv);
> > +      } else {
> > +         priv->recv_msc_serial = ce->serial;
> > +      }
> > +      priv->ust = ce->ust;
> > +      priv->msc = ce->msc;
> > +      break;
> > +   }
> > +   case XCB_PRESENT_EVENT_IDLE_NOTIFY: {
> > +      xcb_present_idle_notify_event_t *ie = (void *) ge;
> > +      int b;
> > +
> > +      for (b = 0; b < sizeof (priv->buffers) / sizeof (priv->buffers[0]); b++) {
> > +         __DRIbuffer        *buf = &priv->buffers[b];
> > +
> > +         if (buf && buf->name == ie->pixmap) {
> > +            /* busy is used in the glx version (in dri3_find_back()) but isn't required here */
> > +            //buf->busy = 0;
> > +
> > +            /* slight change from glx, these buffers are not dynamically allocated so don't 
> > +             * need to be NULL'd.
> > +             */
> > +            if (priv->num_back <= b && b < DRI2_EGL_SURFACE_NUM_BUFFERS) {
> > +               dri3_free_render_buffer(priv, buf);
> > +            }
> > +            break;
> > +         }
> > +      }
> > +      break;
> > +   }
> > +   default:
> > +      break;
> > +   }
> > +   free(ge);
> > +}
> > +
> > +/** dri3_flush_present_events
> > + *
> > + * Process any present events that have been received from the X server
> > + *
> > + * From glx, we additionally invalidate the drawable here if there has a been a special event.
> > + */
> > +static void
> > +dri3_flush_present_events(struct dri2_egl_display *dri2_dpy, struct dri2_egl_surface *priv)
> > +{
> > +   xcb_connection_t     *c = dri2_dpy->conn;
> > +
> > +   /* Check to see if any configuration changes have occurred
> > +    * since we were last invoked
> > +    */
> > +   if (priv->special_event) {
> > +      xcb_generic_event_t    *ev;
> > +
> > +      while ((ev = xcb_poll_for_special_event(c, priv->special_event)) != NULL) {
> > +         xcb_present_generic_event_t *ge = (void *) ev;
> > +         dri3_handle_present_event(priv, ge);
> > +         _eglLog(_EGL_INFO, "DRI3: Invalidating buffer 0x%x\n", priv->dri_drawable);
> > +         (*dri2_dpy->flush->invalidate)(priv->dri_drawable);
> > +      }
> > +   }
> > +}
> > +
> > +/** dri3_update_drawable
> > + *
> > + * from glx
> > + * Called the first time we use the drawable and then
> > + * after we receive present configure notify events to
> > + * track the geometry of the drawable
> > + */
> > +static int
> > +dri3_update_drawable(struct dri2_egl_display *dri2_dpy, __DRIdrawable *driDrawable, void *loaderPrivate)
> > +{
> > +   struct dri2_egl_surface *priv = loaderPrivate;
> > +   xcb_connection_t     *c = dri2_dpy->conn;
> > +
> > +   /* First time through, go get the current drawable geometry
> > +    */
> > +   if (priv->base.Width == 0 || priv->base.Height == 0 || priv->depth == 0) {
> > +      xcb_get_geometry_cookie_t                 geom_cookie;
> > +      xcb_get_geometry_reply_t                  *geom_reply;
> > +      xcb_void_cookie_t                         cookie;
> > +      xcb_generic_error_t                       *error;
> > +
> > +      /* Try to select for input on the window.
> > +       *
> > +       * If the drawable is a window, this will get our events
> > +       * delivered.
> > +       *
> > +       * Otherwise, we'll get a BadWindow error back from this request which
> > +       * will let us know that the drawable is a pixmap instead.
> > +       */
> > +
> > +
> > +      cookie = xcb_present_select_input_checked(c,
> > +                                                (priv->eid = xcb_generate_id(c)),
> > +                                                priv->drawable,
> > +                                                XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY|
> > +                                                XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY|
> > +                                                XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY);
> > +
> > +      /* Create an XCB event queue to hold present events outside of the usual
> > +       * application event queue
> > +       */
> > +      priv->special_event = xcb_register_for_special_xge(c,
> > +                                                         &xcb_present_id,
> > +                                                         priv->eid,
> > +                                                         priv->stamp);
> > +
> > +      geom_cookie = xcb_get_geometry(c, priv->drawable);
> > +
> > +      geom_reply = xcb_get_geometry_reply(c, geom_cookie, NULL);
> > +
> > +      if (!geom_reply)
> > +         return false;
> > +
> > +      priv->base.Width = geom_reply->width;
> > +      priv->base.Height = geom_reply->height;
> > +      priv->depth = geom_reply->depth;
> > +      priv->is_pixmap = false;
> > +
> > +      free(geom_reply);
> > +
> > +      /* Check to see if our select input call failed. If it failed with a
> > +       * BadWindow error, then assume the drawable is a pixmap. Destroy the
> > +       * special event queue created above and mark the drawable as a pixmap
> > +       */
> > +
> > +      error = xcb_request_check(c, cookie);
> > +
> > +      if (error) {
> > +         if (error->error_code != BadWindow) {
> > +            free(error);
> > +            return false;
> > +         }
> > +         priv->is_pixmap = true;
> > +         xcb_unregister_for_special_event(c, priv->special_event);
> > +         priv->special_event = NULL;
> > +      }
> > +   }
> > +   dri3_flush_present_events(dri2_dpy, priv);
> > +   return true;
> > +}
> > +#endif
> >  
> >  /**
> >   * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
> > @@ -212,7 +446,10 @@ dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
> >  
> >     (void) drv;
> >  
> > -   dri2_surf = malloc(sizeof *dri2_surf);
> > +   /* dri2_surf->special_event needs to be initialised as NULL
> > +    * so calloc makes sense here
> > +    */
> > +   dri2_surf = calloc(1, sizeof *dri2_surf);
> >     if (!dri2_surf) {
> >        _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
> >        return NULL;
> > @@ -360,6 +597,17 @@ dri2_x11_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
> >     if (surf->Type == EGL_PBUFFER_BIT)
> >        xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable);
> >  
> > +#ifdef HAVE_DRI3
> > +   /* from glx: dri3_destroy_drawable(). dri2_surf is not necessarily being
> > +    * destroyed so we need to NULL special_event after unregistering it
> > +    */ 
> > +   if (dri2_dpy->dri3_present_and_working && dri2_surf->special_event)
> > +   {
> > +      xcb_unregister_for_special_event(dri2_dpy->conn, dri2_surf->special_event);
> > +      dri2_surf->special_event = NULL;
> > +   }
> > +#endif
> > +
> >     free(surf);
> >  
> >     return EGL_TRUE;
> > @@ -427,6 +675,11 @@ dri2_x11_get_buffers(__DRIdrawable * driDrawable,
> >  
> >     (void) driDrawable;
> >  
> > +#ifdef HAVE_DRI3
> > +   if (dri2_dpy->dri3_present_and_working && !dri3_update_drawable(dri2_dpy, driDrawable, loaderPrivate))
> > +      return false;
> > +#endif
> > +
> >     cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
> >  					    dri2_surf->drawable,
> >  					    count, count, attachments);
> > @@ -461,6 +714,11 @@ dri2_x11_get_buffers_with_format(__DRIdrawable * driDrawable,
> >  
> >     (void) driDrawable;
> >  
> > +#ifdef HAVE_DRI3
> > +   if (dri2_dpy->dri3_present_and_working && !dri3_update_drawable(dri2_dpy, driDrawable, loaderPrivate))
> > +      return false;
> > +#endif
> > +
> >     format_attachments = (xcb_dri2_attach_format_t *) attachments;
> >     cookie = xcb_dri2_get_buffers_with_format_unchecked (dri2_dpy->conn,
> >  							dri2_surf->drawable,
> > @@ -500,12 +758,16 @@ dri2_x11_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
> >  }
> >  
> >  static EGLBoolean
> > -dri2_x11_connect(struct dri2_egl_display *dri2_dpy)
> > +dri2_x11_connect(struct dri2_egl_display *dri2_dpy, _EGLDisplay *disp)
> >  {
> >     xcb_xfixes_query_version_reply_t *xfixes_query;
> >     xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
> >     xcb_dri2_query_version_reply_t *dri2_query;
> >     xcb_dri2_query_version_cookie_t dri2_query_cookie;
> > +#ifdef HAVE_DRI3
> > +   xcb_dri3_query_version_reply_t *dri3_query;
> > +   xcb_dri3_query_version_cookie_t dri3_query_cookie;
> > +#endif
> >     xcb_dri2_connect_reply_t *connect;
> >     xcb_dri2_connect_cookie_t connect_cookie;
> >     xcb_generic_error_t *error;
> > @@ -525,6 +787,44 @@ dri2_x11_connect(struct dri2_egl_display *dri2_dpy)
> >     if (!(extension && extension->present))
> >        return EGL_FALSE;
> >  
> > +#ifdef HAVE_DRI3
> > +   xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri3_id);
> > +   extension = xcb_get_extension_data (dri2_dpy->conn, &xcb_dri3_id);
> > +   if (extension && extension->present) {
> > +      dri3_query_cookie = xcb_dri3_query_version (dri2_dpy->conn,
> > +                                                  XCB_DRI3_MAJOR_VERSION,
> > +                                                  XCB_DRI3_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(error);
> > +         dri2_dpy->dri3_present_and_working = 0;
> > +      } else {
> > +         dri2_dpy->dri3_major = dri3_query->major_version;
> > +         dri2_dpy->dri3_minor = dri3_query->minor_version;
> > +         free(dri3_query);
> > +
> > +         dri2_dpy->fd = dri3_open(dri2_dpy, RootWindow(disp->PlatformDisplay, DefaultScreen(disp->PlatformDisplay)), None);
> > +         if(dri2_dpy->fd < 0)
> > +         {
> > +            dri2_dpy->dri3_present_and_working = 0;
> > +            _eglLog(_EGL_INFO, "DRI2: DRI3 extension not working\n");
> > +         } else {
> > +            dri2_dpy->dri3_present_and_working = 1;
> > +            _eglLog(_EGL_INFO, "DRI2: DRI3 present and working\n");
> > +            close(dri2_dpy->fd);
> > +            dri2_dpy->fd = -1;
> > +         }
> > +      }
> > +   } else {
> > +      dri2_dpy->dri3_present_and_working = 0;
> > +      _eglLog(_EGL_INFO, "DRI2: DRI3 extension not present\n");
> > +   }
> > +#else
> > +   dri2_dpy->dri3_present_and_working = 0;
> > +#endif
> > +
> >     xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn,
> >  						  XCB_XFIXES_MAJOR_VERSION,
> >  						  XCB_XFIXES_MINOR_VERSION);
> > @@ -774,6 +1074,13 @@ dri2_x11_swap_buffers_msc(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
> >     if (dri2_dpy->flush)
> >        (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
> >  
> > +#ifdef HAVE_DRI3
> > +   /* Poll for special events and invalidate the surface if needed.
> > +    */
> > +   if(dri2_dpy->dri3_present_and_working)
> > +      dri3_flush_present_events(dri2_dpy, dri2_surf);
> > +#endif
> > +
> >     cookie = xcb_dri2_swap_buffers_unchecked(dri2_dpy->conn, dri2_surf->drawable,
> >                    msc_hi, msc_lo, divisor_hi, divisor_lo, remainder_hi, remainder_lo);
> >  
> > @@ -794,10 +1101,15 @@ dri2_x11_swap_buffers_msc(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
> >      * happened.  The driver should still be using the viewport hack to catch
> >      * window resizes.
> >      */
> > -   if (dri2_dpy->flush &&
> > -       dri2_dpy->flush->base.version >= 3 && dri2_dpy->flush->invalidate)
> > +   /* With DRI3 we ARE watching for the server's invalidate events like we're
> > +    * supposed to. They're handled in dri3_flush_present_events(), so if we've
> > +    * got DRI3 then we don't need to invalidate here.
> > +    */
> > +   if (!dri2_dpy->dri3_present_and_working && dri2_dpy->flush &&
> > +       dri2_dpy->flush->base.version >= 3 && dri2_dpy->flush->invalidate) {
> > +      _eglLog(_EGL_INFO, "DRI: Invalidating buffer 0x%x\n", dri2_surf->dri_drawable);
> >        (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
> > -
> > +   }
> >     return swap_count;
> >  }
> >  
> > @@ -807,6 +1119,14 @@ dri2_x11_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
> >     struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> >     struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
> >  
> > +#ifdef HAVE_DRI3
> > +   /* from glx: dri3_swap_buffers(). Polls for special events and invalidates
> > +    * the surface if needed.
> > +    */
> > +   if(dri2_dpy->dri3_present_and_working)
> > +      dri3_flush_present_events(dri2_dpy, dri2_surf);
> > +#endif
> > +
> >     if (dri2_dpy->dri2) {
> >        return dri2_x11_swap_buffers_msc(drv, disp, draw, 0, 0, 0) != -1;
> >     } else {
> > @@ -1234,7 +1554,7 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
> >     }
> >  
> >     if (dri2_dpy->conn) {
> > -      if (!dri2_x11_connect(dri2_dpy))
> > +      if (!dri2_x11_connect(dri2_dpy, disp))
> >  	 goto cleanup_conn;
> >     }
> >  
> > @@ -1277,10 +1597,16 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
> >        dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_x11_flush_front_buffer;
> >        dri2_dpy->dri2_loader_extension.getBuffersWithFormat = NULL;
> >     }
> > -      
> > +
> >     dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base;
> >     dri2_dpy->extensions[1] = &image_lookup_extension.base;
> >     dri2_dpy->extensions[2] = NULL;
> > +#ifdef HAVE_DRI3
> > +   if (dri2_dpy->dri3_present_and_working) {
> > +      dri2_dpy->extensions[2] = &dri3_extension.base;
> > +      dri2_dpy->extensions[3] = NULL;
> > +   }
> > +#endif
> >  
> >     dri2_dpy->swap_available = (dri2_dpy->dri2_minor >= 2);
> >     dri2_dpy->invalidate_available = (dri2_dpy->dri2_minor >= 3);
> > diff --git a/src/egl/main/Makefile.am b/src/egl/main/Makefile.am
> > index df8bf28..490930f 100644
> > --- a/src/egl/main/Makefile.am
> > +++ b/src/egl/main/Makefile.am
> > @@ -79,6 +79,10 @@ libEGL_la_LIBADD += ../drivers/dri2/libegl_dri2.la
> >  libEGL_la_LIBADD += $(DLOPEN_LIBS) $(LIBDRM_LIBS)
> >  endif
> >  
> > +if HAVE_DRI3
> > +libEGL_la_LIBADD += $(XCB_DRI3_LIBS)
> > +endif
> > +
> >  include $(top_srcdir)/install-lib-links.mk
> >  
> >  pkgconfigdir = $(libdir)/pkgconfig
> > diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
> > index 6c78928..068d209 100644
> > --- a/src/mesa/drivers/dri/common/dri_util.c
> > +++ b/src/mesa/drivers/dri/common/dri_util.c
> > @@ -73,6 +73,8 @@ setupLoaderExtensions(__DRIscreen *psp,
> >      for (i = 0; extensions[i]; i++) {
> >  	if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0)
> >  	    psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i];
> > +	if (strcmp(extensions[i]->name, __DRI_DRI3) == 0)
> > +	    psp->dri2.dri3 = (__DRIdri3Extension *) extensions[i];
> >  	if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0)
> >  	    psp->dri2.image = (__DRIimageLookupExtension *) extensions[i];
> >  	if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0)
> > diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
> > index 1138bf1..e64a049 100644
> > --- a/src/mesa/drivers/dri/common/dri_util.h
> > +++ b/src/mesa/drivers/dri/common/dri_util.h
> > @@ -175,6 +175,7 @@ struct __DRIscreenRec {
> >  	/* Flag to indicate that this is a DRI2 screen.  Many of the above
> >  	 * fields will not be valid or initializaed in that case. */
> >  	const __DRIdri2LoaderExtension *loader;
> > +	const __DRIdri3Extension *dri3;
> >  	const __DRIimageLookupExtension *image;
> >  	const __DRIuseInvalidateExtension *useInvalidate;
> >      } dri2;
> > diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
> > index 8b3f45b..0b25dc8 100644
> > --- a/src/mesa/drivers/dri/i965/brw_context.c
> > +++ b/src/mesa/drivers/dri/i965/brw_context.c
> > @@ -148,6 +148,9 @@ intel_viewport(struct gl_context *ctx)
> >     __DRIcontext *driContext = brw->driContext;
> >  
> >     if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) {
> > +      if (unlikely(INTEL_DEBUG & DEBUG_DRI))
> > +         fprintf(stderr, "invalidating drawables\n");
> > +
> >        dri2InvalidateDrawable(driContext->driDrawablePriv);
> >        dri2InvalidateDrawable(driContext->driReadablePriv);
> >     }
> > @@ -252,13 +255,12 @@ brw_init_driver_functions(struct brw_context *brw,
> >     _mesa_init_driver_functions(functions);
> >  
> >     /* GLX uses DRI2 invalidate events to handle window resizing.
> > -    * Unfortunately, EGL does not - libEGL is written in XCB (not Xlib),
> > -    * which doesn't provide a mechanism for snooping the event queues.
> > +    * EGL backend can only receive the events when DRI3 is present.
> >      *
> > -    * So EGL still relies on viewport hacks to handle window resizing.
> > -    * This should go away with DRI3000.
> > +    * So DRI2 relies on viewport hacks to handle window resizing.
> >      */
> > -   if (!brw->driContext->driScreenPriv->dri2.useInvalidate)
> > +   if (!brw->driContext->driScreenPriv->dri2.useInvalidate &&
> > +       !brw->driContext->driScreenPriv->dri2.dri3)
> >        functions->Viewport = intel_viewport;
> >  
> >     functions->Flush = intel_glFlush;
> > 
> 




More information about the mesa-dev mailing list