diff mbox

present: Send GLX_BufferSwapComplete events from present extension

Message ID 1385103256-24620-1-git-send-email-keithp@keithp.com (mailing list archive)
State Not Applicable
Headers show

Commit Message

Keith Packard Nov. 22, 2013, 6:54 a.m. UTC
This allows GL to support the GLX_INTEL_swap_event extension

Signed-off-by: Keith Packard <keithp@keithp.com>
---

This is the X server side; the mesa patch will be sent shortly (it's tiny)

 glx/Makefile.am         |  3 ++-
 glx/glxcmds.c           | 69 +++++++++++++++++++++++++++++++++++++++++++++++++
 glx/glxdri2.c           | 26 +++++--------------
 glx/glxext.c            |  3 +++
 glx/glxserver.h         |  9 +++++++
 present/present.h       |  9 +++++++
 present/present_event.c | 10 +++++++
 7 files changed, 109 insertions(+), 20 deletions(-)

Comments

Eric Anholt Nov. 25, 2013, 10:46 p.m. UTC | #1
Keith Packard <keithp@keithp.com> writes:

> This allows GL to support the GLX_INTEL_swap_event extension
>
> Signed-off-by: Keith Packard <keithp@keithp.com>

There's a minor behavior change that the event now gets sent to the
drawable owner rather than the caller of DRI2SwapBuffers.

I don't expect it to matter in practice (I expect that the
swap-requesting client using this GLX extension is also the
drawable-creating one), and either choice seems wrong compared to "send
the event to everyone listening for the event on this drawable".  That
would be a separate change, anyway.

Reviewed-by: Eric Anholt <eric@anholt.net>
Keith Packard Nov. 26, 2013, 2:39 a.m. UTC | #2
Eric Anholt <eric@anholt.net> writes:

> There's a minor behavior change that the event now gets sent to the
> drawable owner rather than the caller of DRI2SwapBuffers.

Yeah, probably not ideal, especially when the GLX drawable is created
using the window XID (as is the case for some older GLX clients). I
don't have the original client at the time the event is generated, but I
think I can go back and stick it in; will require tracking when the
client exits, of course.

> I don't expect it to matter in practice (I expect that the
> swap-requesting client using this GLX extension is also the
> drawable-creating one), and either choice seems wrong compared to "send
> the event to everyone listening for the event on this drawable".  That
> would be a separate change, anyway.

I think the original behaviour, sending the event to the client who sent
the PresentPixmap request is the only sane plan, and only a bit more
complicated than sending it to the drawable owner.

I'll cook up an alternate patch and send that along; we can then compare
the two approaches at least.
Keith Packard Nov. 26, 2013, 5:35 a.m. UTC | #3
I've split the GLX_INTEL_swap_event enabling patch into four bits -- the first
three just fix the existing code to track SBC values correctly and to fix
wait_for_sbc. The fourth is the trivial patch to actually turn on the new
extension; all of the hard work for that is actually dealt with in the X
server.

 [PATCH 1/4] dri3: Clean up struct dri3_drawable

Trivial struct member cleanup -- a couple of unused fields, and one oddly
placed field.

 [PATCH 2/4] dri3: Track full 64-bit SBC numbers, instead of just

This switches all of the internal SBC tracking to use 64-bit values. I use
uint64_t because I don't trust compilers with signed integer comparisons that
may wrap any more.

 [PATCH 3/4] dri3: Fix dri3_wait_for_sbc to wait for completion of

This one makes wait_for_sbc actually wait for the completion of the specified
swap, rather than the queuing of that value. Makes *far* more sense this way.

 [PATCH 4/4] dri3: Enable GLX_INTEL_swap_event

The trivial patch that just adds the extension to the list.

-keith
diff mbox

Patch

diff --git a/glx/Makefile.am b/glx/Makefile.am
index 5f28e87..44d3a7d 100644
--- a/glx/Makefile.am
+++ b/glx/Makefile.am
@@ -20,7 +20,8 @@  AM_CPPFLAGS = \
 	-I$(top_srcdir)/hw/xfree86/os-support/bus \
 	-I$(top_srcdir)/hw/xfree86/common \
 	-I$(top_srcdir)/hw/xfree86/dri \
-	-I$(top_srcdir)/mi
+	-I$(top_srcdir)/mi \
+	-I$(top_srcdir)/present
 
 if DRI2_AIGLX
 AM_CPPFLAGS += -I$(top_srcdir)/hw/xfree86/dri2
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index efa4aec..2c5de70 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -2468,3 +2468,72 @@  __glXDisp_ClientInfo(__GLXclientState * cl, GLbyte * pc)
 
     return Success;
 }
+
+#include <GL/glxtokens.h>
+
+void
+__glXsendSwapEvent(__GLXdrawable *drawable, int type, CARD64 ust,
+                   CARD64 msc, CARD32 sbc)
+{
+    ClientPtr client = clients[CLIENT_ID(drawable->drawId)];
+
+    xGLXBufferSwapComplete2 wire =  {
+        .type = __glXEventBase + GLX_BufferSwapComplete
+    };
+
+    if (!client)
+        return;
+
+    if (!(drawable->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK))
+        return;
+
+    wire.event_type = type;
+    wire.drawable = drawable->drawId;
+    wire.ust_hi = ust >> 32;
+    wire.ust_lo = ust & 0xffffffff;
+    wire.msc_hi = msc >> 32;
+    wire.msc_lo = msc & 0xffffffff;
+    wire.sbc = sbc;
+
+    WriteEventsToClient(client, 1, (xEvent *) &wire);
+}
+
+#if PRESENT
+static void
+__glXpresentCompleteNotify(WindowPtr window, CARD8 present_mode, CARD32 serial,
+                           uint64_t ust, uint64_t msc)
+{
+    __GLXdrawable *drawable;
+    int error;
+    int glx_type;
+    int rc;
+
+    rc = dixLookupResourceByType((pointer *) &drawable, window->drawable.id,
+                                 __glXDrawableRes, serverClient, DixGetAttrAccess);
+
+    if (rc != Success)
+        return;
+
+    switch(present_mode) {
+    case PresentCompleteModeFlip:
+        glx_type = GLX_FLIP_COMPLETE_INTEL;
+        break;
+    case PresentCompleteModeCopy:
+        glx_type = GLX_BLIT_COMPLETE_INTEL;
+        break;
+    default:
+        glx_type = 0;
+        break;
+    }
+        
+    __glXsendSwapEvent(drawable, glx_type, ust, msc, serial);
+}
+
+#include <present.h>
+
+void
+__glXregisterPresentCompleteNotify(void)
+{
+    present_register_complete_notify(__glXpresentCompleteNotify);
+}
+#endif
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index 1d74c8f..9d3f3c3 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -177,36 +177,24 @@  __glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust,
                   CARD64 msc, CARD32 sbc)
 {
     __GLXdrawable *drawable = data;
-    xGLXBufferSwapComplete2 wire =  {
-        .type = __glXEventBase + GLX_BufferSwapComplete
-    };
-
-    if (!(drawable->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK))
-        return;
-
+    int glx_type;
     switch (type) {
     case DRI2_EXCHANGE_COMPLETE:
-        wire.event_type = GLX_EXCHANGE_COMPLETE_INTEL;
+        glx_type = GLX_EXCHANGE_COMPLETE_INTEL;
         break;
     case DRI2_BLIT_COMPLETE:
-        wire.event_type = GLX_BLIT_COMPLETE_INTEL;
+        glx_type = GLX_BLIT_COMPLETE_INTEL;
         break;
     case DRI2_FLIP_COMPLETE:
-        wire.event_type = GLX_FLIP_COMPLETE_INTEL;
+        glx_type = GLX_FLIP_COMPLETE_INTEL;
         break;
     default:
         /* unknown swap completion type */
-        wire.event_type = 0;
+        glx_type = 0;
         break;
     }
-    wire.drawable = drawable->drawId;
-    wire.ust_hi = ust >> 32;
-    wire.ust_lo = ust & 0xffffffff;
-    wire.msc_hi = msc >> 32;
-    wire.msc_lo = msc & 0xffffffff;
-    wire.sbc = sbc;
-
-    WriteEventsToClient(client, 1, (xEvent *) &wire);
+    
+    __glXsendSwapEvent(drawable, glx_type, ust, msc, sbc);
 }
 
 /*
diff --git a/glx/glxext.c b/glx/glxext.c
index 3a7de28..601d08a 100644
--- a/glx/glxext.c
+++ b/glx/glxext.c
@@ -399,6 +399,9 @@  GlxExtensionInit(void)
 
     __glXErrorBase = extEntry->errorBase;
     __glXEventBase = extEntry->eventBase;
+#if PRESENT
+    __glXregisterPresentCompleteNotify();
+#endif
 }
 
 /************************************************************************/
diff --git a/glx/glxserver.h b/glx/glxserver.h
index 5e29abb..f862b63 100644
--- a/glx/glxserver.h
+++ b/glx/glxserver.h
@@ -120,6 +120,15 @@  void glxResumeClients(void);
 void __glXsetGetProcAddress(void (*(*get_proc_address) (const char *)) (void));
 void *__glGetProcAddress(const char *);
 
+void
+__glXsendSwapEvent(__GLXdrawable *drawable, int type, CARD64 ust,
+                   CARD64 msc, CARD32 sbc);
+
+#if PRESENT
+void
+__glXregisterPresentCompleteNotify(void);
+#endif
+
 /*
 ** State kept per client.
 */
diff --git a/present/present.h b/present/present.h
index 6a451fb..0e3bdc0 100644
--- a/present/present.h
+++ b/present/present.h
@@ -115,4 +115,13 @@  present_event_abandon(RRCrtcPtr crtc);
 extern _X_EXPORT Bool
 present_screen_init(ScreenPtr screen, present_screen_info_ptr info);
 
+typedef void (*present_complete_notify_proc)(WindowPtr window,
+                                             CARD8 mode,
+                                             CARD32 serial,
+                                             uint64_t ust,
+                                             uint64_t msc);
+
+extern _X_EXPORT void
+present_register_complete_notify(present_complete_notify_proc proc);
+
 #endif /* _PRESENT_H_ */
diff --git a/present/present_event.c b/present/present_event.c
index a8f7176..f0d509e 100644
--- a/present/present_event.c
+++ b/present/present_event.c
@@ -137,6 +137,14 @@  present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw,
     }
 }
 
+static present_complete_notify_proc complete_notify;
+
+void
+present_register_complete_notify(present_complete_notify_proc proc)
+{
+    complete_notify = proc;
+}
+
 void
 present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc)
 {
@@ -165,6 +173,8 @@  present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 se
             }
         }
     }
+    if (complete_notify)
+        (*complete_notify)(window, mode, serial, ust, msc);
 }
 
 void