st/egl: Add event support to the native display interface.
authorChia-I Wu <olv@lunarg.com>
Sun, 21 Feb 2010 02:58:22 +0000 (10:58 +0800)
committerChia-I Wu <olv@lunarg.com>
Fri, 5 Mar 2010 02:19:05 +0000 (10:19 +0800)
There is only invalid_surface event right now.  When EGL receives the
event, it sets the force_validate flag of the context binding to the
surface.  This helps skip an unnecessary check.

src/gallium/state_trackers/egl/common/egl_g3d.c
src/gallium/state_trackers/egl/common/native.h
src/gallium/state_trackers/egl/kms/native_kms.c
src/gallium/state_trackers/egl/kms/native_kms.h
src/gallium/state_trackers/egl/x11/native_dri2.c
src/gallium/state_trackers/egl/x11/native_x11.c
src/gallium/state_trackers/egl/x11/native_x11.h
src/gallium/state_trackers/egl/x11/native_ximage.c

index 04268c71c5a4fdc4447697acf7967f97928f593e..ddb1ef1bf1f3c20cc489547236deb4b93f2486f9 100644 (file)
@@ -531,6 +531,24 @@ egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private)
    egl_g3d_validate_context(gctx->base.Resource.Display, &gctx->base);
 }
 
+static void
+egl_g3d_invalid_surface(struct native_display *ndpy,
+                        struct native_surface *nsurf,
+                        unsigned int seq_num)
+{
+   /* XXX not thread safe? */
+   struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
+   struct egl_g3d_context *gctx = egl_g3d_context(gsurf->base.CurrentContext);
+
+   /* set force_validate to skip an unnecessary check */
+   if (gctx)
+      gctx->force_validate = TRUE;
+}
+
+static struct native_event_handler egl_g3d_native_event_handler = {
+   .invalid_surface = egl_g3d_invalid_surface
+};
+
 static EGLBoolean
 egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
 {
@@ -575,12 +593,14 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
    }
    dpy->DriverData = gdpy;
 
-   gdpy->native = native_create_display(dpy->NativeDisplay);
+   gdpy->native = native_create_display(dpy->NativeDisplay,
+         &egl_g3d_native_event_handler);
    if (!gdpy->native) {
       _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
       goto fail;
    }
 
+   gdpy->native->user_data = (void *) dpy;
    gdpy->native->screen->flush_frontbuffer = egl_g3d_flush_frontbuffer;
    gdpy->native->screen->update_buffer = egl_g3d_update_buffer;
 
@@ -776,6 +796,7 @@ egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
       return NULL;
    }
 
+   nsurf->user_data = &gsurf->base;
    gsurf->native = nsurf;
 
    gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) ?
index 4f9758545abab6e0e876377ab5d4702e14f54dd9..1bf2804db5d21db0ba86706a33491bc527b21666 100644 (file)
@@ -69,6 +69,11 @@ struct native_probe {
 };
 
 struct native_surface {
+   /**
+    * Available for caller's use.
+    */
+   void *user_data;
+
    void (*destroy)(struct native_surface *nsurf);
 
    /**
@@ -143,6 +148,11 @@ struct native_display {
     */
    struct pipe_screen *screen;
 
+   /**
+    * Available for caller's use.
+    */
+   void *user_data;
+
    void (*destroy)(struct native_display *ndpy);
 
    /**
@@ -238,6 +248,20 @@ struct native_display_modeset {
                       const struct native_mode *nmode);
 };
 
+/**
+ * The handler for events that a native display may generate.  The events are
+ * generated asynchronously and the handler may be called by any thread at any
+ * time.
+ */
+struct native_event_handler {
+   /**
+    * This function is called when a surface needs to be validated.
+    */
+   void (*invalid_surface)(struct native_display *ndpy,
+                           struct native_surface *nsurf,
+                           unsigned int seq_num);
+};
+
 /**
  * Test whether an attachment is set in the mask.
  */
@@ -267,6 +291,7 @@ const char *
 native_get_name(void);
 
 struct native_display *
-native_create_display(EGLNativeDisplayType dpy);
+native_create_display(EGLNativeDisplayType dpy,
+                      struct native_event_handler *handler);
 
 #endif /* _NATIVE_H_ */
index aedf3d430ca15292422680470e02c9306685ca3d..90c82eaf6ce4d93af828d9e953412f90ccf74b9d 100644 (file)
@@ -201,6 +201,8 @@ kms_surface_swap_buffers(struct native_surface *nsurf)
 
    /* the front/back textures are swapped */
    ksurf->sequence_number++;
+   kdpy->event_handler->invalid_surface(&kdpy->base,
+         &ksurf->base, ksurf->sequence_number);
 
    return TRUE;
 }
@@ -762,7 +764,9 @@ static struct native_display_modeset kms_display_modeset = {
 };
 
 static struct native_display *
-kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api)
+kms_create_display(EGLNativeDisplayType dpy,
+                   struct native_event_handler *event_handler,
+                   struct drm_api *api)
 {
    struct kms_display *kdpy;
 
@@ -770,6 +774,8 @@ kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api)
    if (!kdpy)
       return NULL;
 
+   kdpy->event_handler = event_handler;
+
    kdpy->api = api;
    if (!kdpy->api) {
       _eglLog(_EGL_WARNING, "failed to create DRM API");
@@ -845,7 +851,8 @@ native_get_name(void)
 }
 
 struct native_display *
-native_create_display(EGLNativeDisplayType dpy)
+native_create_display(EGLNativeDisplayType dpy,
+                      struct native_event_handler *event_handler)
 {
    struct native_display *ndpy = NULL;
 
@@ -853,7 +860,7 @@ native_create_display(EGLNativeDisplayType dpy)
       drm_api = drm_api_create();
 
    if (drm_api)
-      ndpy = kms_create_display(dpy, drm_api);
+      ndpy = kms_create_display(dpy, event_handler, drm_api);
 
    return ndpy;
 }
index 095186e3cf367cab95e0cef8f26de6e0249d9bb1..f9cbcb158b5ddece6821aa44868712eaa6fd3542 100644 (file)
@@ -53,6 +53,8 @@ struct kms_crtc {
 struct kms_display {
    struct native_display base;
 
+   struct native_event_handler *event_handler;
+
    int fd;
    struct drm_api *api;
    drmModeResPtr resources;
index 74d3d104b941e00b3b00d5cc04c22fd9aa261bb2..858033e1c1059e9120ba90544672b1416b4f82ae 100644 (file)
@@ -48,6 +48,8 @@ struct dri2_display {
    Display *dpy;
    boolean own_dpy;
 
+   struct native_event_handler *event_handler;
+
    struct drm_api *api;
    struct x11_screen *xscr;
    int xscr_number;
@@ -324,8 +326,11 @@ dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
             DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
 
    /* force buffers to be updated in next validation call */
-   if (!dri2_surface_receive_events(&dri2surf->base))
+   if (!dri2_surface_receive_events(&dri2surf->base)) {
       dri2surf->server_stamp++;
+      dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
+            &dri2surf->base, dri2surf->server_stamp);
+   }
 
    return TRUE;
 }
@@ -353,8 +358,11 @@ dri2_surface_swap_buffers(struct native_surface *nsurf)
             DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
 
    /* force buffers to be updated in next validation call */
-   if (!dri2_surface_receive_events(&dri2surf->base))
+   if (!dri2_surface_receive_events(&dri2surf->base)) {
       dri2surf->server_stamp++;
+      dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
+            &dri2surf->base, dri2surf->server_stamp);
+   }
 
    return TRUE;
 }
@@ -737,7 +745,10 @@ dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable,
       return;
 
    dri2surf = dri2_surface(nsurf);
+
    dri2surf->server_stamp++;
+   dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
+         &dri2surf->base, dri2surf->server_stamp);
 }
 
 /**
@@ -796,7 +807,9 @@ dri2_display_hash_table_compare(void *key1, void *key2)
 }
 
 struct native_display *
-x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api)
+x11_create_dri2_display(EGLNativeDisplayType dpy,
+                        struct native_event_handler *event_handler,
+                        struct drm_api *api)
 {
    struct dri2_display *dri2dpy;
 
@@ -804,6 +817,7 @@ x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api)
    if (!dri2dpy)
       return NULL;
 
+   dri2dpy->event_handler = event_handler;
    dri2dpy->api = api;
 
    dri2dpy->dpy = dpy;
index 3add95d0aca272c35f4c3010ec5112bfd9f89eb6..7b4fe63fa07d33943513f95720d2a126138ccbf6 100644 (file)
@@ -126,7 +126,8 @@ native_get_name(void)
 }
 
 struct native_display *
-native_create_display(EGLNativeDisplayType dpy)
+native_create_display(EGLNativeDisplayType dpy,
+                      struct native_event_handler *event_handler)
 {
    struct native_display *ndpy = NULL;
    boolean force_sw;
@@ -136,7 +137,7 @@ native_create_display(EGLNativeDisplayType dpy)
 
    force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE);
    if (api && !force_sw) {
-      ndpy = x11_create_dri2_display(dpy, api);
+      ndpy = x11_create_dri2_display(dpy, event_handler, api);
    }
 
    if (!ndpy) {
@@ -150,7 +151,7 @@ native_create_display(EGLNativeDisplayType dpy)
        */
       use_shm = FALSE;
       _eglLog(level, "use software%s fallback", (use_shm) ? " (SHM)" : "");
-      ndpy = x11_create_ximage_display(dpy, use_shm);
+      ndpy = x11_create_ximage_display(dpy, event_handler, use_shm);
    }
 
    return ndpy;
index 622ddac5df6cddcf0ed63c197eb1640154c92c90..8c6a7d9349753bf3b28ead3ed7050a9197e5caf1 100644 (file)
 #include "common/native.h"
 
 struct native_display *
-x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm);
+x11_create_ximage_display(EGLNativeDisplayType dpy,
+                          struct native_event_handler *event_handler,
+                          boolean use_xshm);
 
 struct native_display *
-x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api);
+x11_create_dri2_display(EGLNativeDisplayType dpy,
+                        struct native_event_handler *event_handler,
+                        struct drm_api *api);
 
 #endif /* _NATIVE_X11_H_ */
index a8633b1501ee32782bc7c06373c11574b2b1176e..5e0270c296301f294891b30d63563c606347f48d 100644 (file)
@@ -56,6 +56,8 @@ struct ximage_display {
    struct x11_screen *xscr;
    int xscr_number;
 
+   struct native_event_handler *event_handler;
+
    boolean use_xshm;
 
    struct pipe_winsys *winsys;
@@ -228,6 +230,16 @@ ximage_surface_update_geometry(struct native_surface *nsurf)
    return updated;
 }
 
+static void
+ximage_surface_notify_invalid(struct native_surface *nsurf)
+{
+   struct ximage_surface *xsurf = ximage_surface(nsurf);
+   struct ximage_display *xdpy = xsurf->xdpy;
+
+   xdpy->event_handler->invalid_surface(&xdpy->base,
+         &xsurf->base, xsurf->server_stamp);
+}
+
 /**
  * Update the buffers of the surface.  It is a slow function due to the
  * round-trip to the server.
@@ -339,6 +351,7 @@ ximage_surface_flush_frontbuffer(struct native_surface *nsurf)
          NATIVE_ATTACHMENT_FRONT_LEFT);
    /* force buffers to be updated in next validation call */
    xsurf->server_stamp++;
+   ximage_surface_notify_invalid(&xsurf->base);
 
    return ret;
 }
@@ -354,6 +367,7 @@ ximage_surface_swap_buffers(struct native_surface *nsurf)
    ret = ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT);
    /* force buffers to be updated in next validation call */
    xsurf->server_stamp++;
+   ximage_surface_notify_invalid(&xsurf->base);
 
    xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT];
    xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT];
@@ -703,7 +717,9 @@ ximage_display_destroy(struct native_display *ndpy)
 }
 
 struct native_display *
-x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm)
+x11_create_ximage_display(EGLNativeDisplayType dpy,
+                          struct native_event_handler *event_handler,
+                          boolean use_xshm)
 {
    struct ximage_display *xdpy;
 
@@ -728,6 +744,8 @@ x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm)
       return NULL;
    }
 
+   xdpy->event_handler = event_handler;
+
    xdpy->use_xshm =
       (use_xshm && x11_screen_support(xdpy->xscr, X11_SCREEN_EXTENSION_XSHM));