[Mesa-dev] [PATCH 2/4] glx/dri2: add and use new driver hook flush_with_flags
Marek Olšák
maraeo at gmail.com
Fri Nov 23 11:35:33 PST 2012
---
include/GL/internal/dri_interface.h | 29 ++++-
src/glx/dri2_glx.c | 144 ++++++++++++++++---------
src/mesa/drivers/dri/intel/intel_screen.c | 2 +-
src/mesa/drivers/dri/nouveau/nouveau_screen.c | 2 +-
src/mesa/drivers/dri/radeon/radeon_screen.c | 2 +-
5 files changed, 125 insertions(+), 54 deletions(-)
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 1e0f1d0..718b53b 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -267,7 +267,13 @@ struct __DRItexBufferExtensionRec {
* Used by drivers that implement DRI2
*/
#define __DRI2_FLUSH "DRI2_Flush"
-#define __DRI2_FLUSH_VERSION 3
+#define __DRI2_FLUSH_VERSION 4
+
+#define __DRI2_FLUSH_DRAWABLE (1 << 0) /* the drawable should be flushed. */
+#define __DRI2_FLUSH_CONTEXT (1 << 1) /* glFlush should be called */
+
+enum __DRI2throttleReason;
+
struct __DRI2flushExtensionRec {
__DRIextension base;
void (*flush)(__DRIdrawable *drawable);
@@ -281,6 +287,27 @@ struct __DRI2flushExtensionRec {
* \since 3
*/
void (*invalidate)(__DRIdrawable *drawable);
+
+ /**
+ * This function reduces the number of flushes in the driver by combining
+ * several operations into one call.
+ *
+ * It can:
+ * - throttle
+ * - flush a drawable
+ * - flush a context
+ *
+ * \param context the context
+ * \param drawable the drawable to flush
+ * \param flags a combination of _DRI2_FLUSH_xxx flags
+ * \param throttle_reason the reason for throttling, 0 = no throttling
+ *
+ * \since 4
+ */
+ void (*flush_with_flags)(__DRIcontext *ctx,
+ __DRIdrawable *drawable,
+ unsigned flags,
+ enum __DRI2throttleReason throttle_reason);
};
diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c
index 30f6913..5438def 100644
--- a/src/glx/dri2_glx.c
+++ b/src/glx/dri2_glx.c
@@ -509,6 +509,15 @@ dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
return 1;
}
+static __DRIcontext *
+dri2GetCurrentContext()
+{
+ struct glx_context *gc = __glXGetCurrentContext();
+ struct dri2_context *dri2Ctx = (struct dri2_context *)gc;
+
+ return dri2Ctx ? dri2Ctx->driContext : NULL;
+}
+
/**
* dri2Throttle - Request driver throttling
*
@@ -522,10 +531,7 @@ dri2Throttle(struct dri2_screen *psc,
enum __DRI2throttleReason reason)
{
if (psc->throttle) {
- struct glx_context *gc = __glXGetCurrentContext();
- struct dri2_context *dri2Ctx = (struct dri2_context *)gc;
- __DRIcontext *ctx =
- (dri2Ctx) ? dri2Ctx->driContext : NULL;
+ __DRIcontext *ctx = dri2GetCurrentContext();
psc->throttle->throttle(ctx, draw->driDrawable, reason);
}
@@ -550,14 +556,25 @@ __dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y,
xrect.width = width;
xrect.height = height;
- if (flush) {
- glFlush();
+ if (psc->f && psc->f->base.version >= 4) {
+ unsigned flags = flush ? __DRI2_FLUSH_CONTEXT : 0;
+ __DRIcontext *ctx = dri2GetCurrentContext();
+
+ if (ctx) {
+ (*psc->f->flush_with_flags)(ctx, priv->driDrawable, flags, reason);
+ }
}
+ else {
+ if (flush) {
+ glFlush();
+ }
- if (psc->f)
- (*psc->f->flush) (priv->driDrawable);
+ if (psc->f) {
+ (*psc->f->flush) (priv->driDrawable);
+ }
- dri2Throttle(psc, priv, reason);
+ dri2Throttle(psc, priv, reason);
+ }
region = XFixesCreateRegion(psc->base.dpy, &xrect, 1);
DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region,
@@ -734,6 +751,50 @@ static void show_fps(struct dri2_drawable *draw)
}
static int64_t
+dri2XcbSwapBuffers(Display *dpy,
+ __GLXDRIdrawable *pdraw,
+ int64_t target_msc,
+ int64_t divisor,
+ int64_t remainder)
+{
+ xcb_dri2_swap_buffers_cookie_t swap_buffers_cookie;
+ xcb_dri2_swap_buffers_reply_t *swap_buffers_reply;
+ uint32_t target_msc_hi, target_msc_lo;
+ uint32_t divisor_hi, divisor_lo;
+ uint32_t remainder_hi, remainder_lo;
+ int64_t ret = 0;
+ xcb_connection_t *c = XGetXCBConnection(dpy);
+
+ split_counter(target_msc, &target_msc_hi, &target_msc_lo);
+ split_counter(divisor, &divisor_hi, &divisor_lo);
+ split_counter(remainder, &remainder_hi, &remainder_lo);
+
+ swap_buffers_cookie =
+ xcb_dri2_swap_buffers_unchecked(c, pdraw->xDrawable,
+ target_msc_hi, target_msc_lo,
+ divisor_hi, divisor_lo,
+ remainder_hi, remainder_lo);
+
+ /* Immediately wait on the swapbuffers reply. If we didn't, we'd have
+ * to do so some time before reusing a (non-pageflipped) backbuffer.
+ * Otherwise, the new rendering could get ahead of the X Server's
+ * dispatch of the swapbuffer and you'd display garbage.
+ *
+ * We use XSync() first to reap the invalidate events through the event
+ * filter, to ensure that the next drawing doesn't use an invalidated
+ * buffer.
+ */
+ XSync(dpy, False);
+
+ swap_buffers_reply =
+ xcb_dri2_swap_buffers_reply(c, swap_buffers_cookie, NULL);
+ ret = merge_counter(swap_buffers_reply->swap_hi,
+ swap_buffers_reply->swap_lo);
+ free(swap_buffers_reply);
+ return ret;
+}
+
+static int64_t
dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
int64_t remainder, Bool flush)
{
@@ -742,7 +803,7 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc;
struct dri2_display *pdp =
(struct dri2_display *)dpyPriv->dri2Display;
- CARD64 ret = 0;
+ int64_t ret = 0;
/* Check we have the right attachments */
if (!priv->have_back)
@@ -753,51 +814,34 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
__dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height,
__DRI2_THROTTLE_SWAPBUFFER, flush);
} else {
- xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
- xcb_dri2_swap_buffers_cookie_t swap_buffers_cookie;
- xcb_dri2_swap_buffers_reply_t *swap_buffers_reply;
- uint32_t target_msc_hi, target_msc_lo;
- uint32_t divisor_hi, divisor_lo;
- uint32_t remainder_hi, remainder_lo;
-
- if (flush) {
- glFlush();
+ if (psc->f && psc->f->base.version >= 4) {
+ unsigned flags = flush ? __DRI2_FLUSH_CONTEXT : 0;
+ __DRIcontext *ctx = dri2GetCurrentContext();
+
+ if (ctx) {
+ (*psc->f->flush_with_flags)(ctx, priv->driDrawable, flags,
+ __DRI2_THROTTLE_SWAPBUFFER);
+ }
+ ret = dri2XcbSwapBuffers(pdraw->psc->dpy, pdraw,
+ target_msc, divisor, remainder);
}
+ else {
+ if (flush) {
+ glFlush();
+ }
- if (psc->f) {
- struct glx_context *gc = __glXGetCurrentContext();
+ if (psc->f) {
+ struct glx_context *gc = __glXGetCurrentContext();
- if (gc) {
- (*psc->f->flush)(priv->driDrawable);
+ if (gc) {
+ (*psc->f->flush)(priv->driDrawable);
+ }
}
- }
- dri2Throttle(psc, priv, __DRI2_THROTTLE_SWAPBUFFER);
-
- split_counter(target_msc, &target_msc_hi, &target_msc_lo);
- split_counter(divisor, &divisor_hi, &divisor_lo);
- split_counter(remainder, &remainder_hi, &remainder_lo);
-
- swap_buffers_cookie =
- xcb_dri2_swap_buffers_unchecked(c, pdraw->xDrawable,
- target_msc_hi, target_msc_lo,
- divisor_hi, divisor_lo,
- remainder_hi, remainder_lo);
- /* Immediately wait on the swapbuffers reply. If we didn't, we'd have
- * to do so some time before reusing a (non-pageflipped) backbuffer.
- * Otherwise, the new rendering could get ahead of the X Server's
- * dispatch of the swapbuffer and you'd display garbage.
- *
- * We use XSync() first to reap the invalidate events through the event
- * filter, to ensure that the next drawing doesn't use an invalidated
- * buffer.
- */
- XSync(pdraw->psc->dpy, False);
- swap_buffers_reply =
- xcb_dri2_swap_buffers_reply(c, swap_buffers_cookie, NULL);
- ret = merge_counter(swap_buffers_reply->swap_hi,
- swap_buffers_reply->swap_lo);
- free(swap_buffers_reply);
+ dri2Throttle(psc, priv, __DRI2_THROTTLE_SWAPBUFFER);
+ ret = dri2XcbSwapBuffers(pdraw->psc->dpy, pdraw,
+ target_msc, divisor, remainder);
+ }
}
if (psc->show_fps) {
diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
index 4e2742f..76cc527 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -188,7 +188,7 @@ intelDRI2Flush(__DRIdrawable *drawable)
}
static const struct __DRI2flushExtensionRec intelFlushExtension = {
- .base = { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
+ .base = { __DRI2_FLUSH, 3 },
.flush = intelDRI2Flush,
.invalidate = dri2InvalidateDrawable,
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_screen.c b/src/mesa/drivers/dri/nouveau/nouveau_screen.c
index dc6d758..ca39fff 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_screen.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_screen.c
@@ -216,7 +216,7 @@ nouveau_drawable_flush(__DRIdrawable *draw)
}
static const struct __DRI2flushExtensionRec nouveau_flush_extension = {
- { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
+ { __DRI2_FLUSH, 3 },
nouveau_drawable_flush,
dri2InvalidateDrawable,
};
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c
index 6f4750a..a5fad70 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.c
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.c
@@ -193,7 +193,7 @@ radeonDRI2Flush(__DRIdrawable *drawable)
}
static const struct __DRI2flushExtensionRec radeonFlushExtension = {
- { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
+ { __DRI2_FLUSH, 3 },
radeonDRI2Flush,
dri2InvalidateDrawable,
};
--
1.7.10.4
More information about the mesa-dev
mailing list