glx/dri2: add and use new driver hook flush_with_flags
This commit is contained in:
parent
5b7e9b7360
commit
4a486f8bf2
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
@ -733,6 +750,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,33 @@ 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 (psc->f && psc->f->base.version >= 4) {
|
||||
unsigned flags = flush ? __DRI2_FLUSH_CONTEXT : 0;
|
||||
__DRIcontext *ctx = dri2GetCurrentContext();
|
||||
|
||||
if (flush) {
|
||||
glFlush();
|
||||
}
|
||||
|
||||
if (psc->f) {
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
|
||||
if (gc) {
|
||||
(*psc->f->flush)(priv->driDrawable);
|
||||
if (ctx) {
|
||||
(*psc->f->flush_with_flags)(ctx, priv->driDrawable, flags,
|
||||
__DRI2_THROTTLE_SWAPBUFFER);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (flush) {
|
||||
glFlush();
|
||||
}
|
||||
|
||||
dri2Throttle(psc, priv, __DRI2_THROTTLE_SWAPBUFFER);
|
||||
if (psc->f) {
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
|
||||
split_counter(target_msc, &target_msc_hi, &target_msc_lo);
|
||||
split_counter(divisor, &divisor_hi, &divisor_lo);
|
||||
split_counter(remainder, &remainder_hi, &remainder_lo);
|
||||
if (gc) {
|
||||
(*psc->f->flush)(priv->driDrawable);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -193,7 +193,7 @@ radeonDRI2Flush(__DRIdrawable *drawable)
|
|||
}
|
||||
|
||||
static const struct __DRI2flushExtensionRec radeonFlushExtension = {
|
||||
{ __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
|
||||
{ __DRI2_FLUSH, 3 },
|
||||
radeonDRI2Flush,
|
||||
dri2InvalidateDrawable,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue