From 57e09c35d3f6bf55a2b4d00af392848334831dde Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 15 Oct 2016 20:35:14 +0100 Subject: [PATCH] one-big-patch --- include/GL/internal/dri_interface.h | 12 ++++++- src/glx/dri2_glx.c | 16 +++++++-- src/loader/loader_dri3_helper.c | 53 ++++++++++++++++++++++++++++- src/loader/loader_dri3_helper.h | 3 ++ src/mesa/drivers/dri/common/dri_util.c | 6 ++++ src/mesa/drivers/dri/common/dri_util.h | 4 +++ src/mesa/drivers/dri/i965/brw_context.c | 38 ++++++--------------- src/mesa/drivers/dri/i965/brw_context.h | 23 +++++++++++-- src/mesa/drivers/dri/i965/intel_screen.c | 5 +-- src/mesa/drivers/dri/i965/intel_tex_image.c | 5 ++- 10 files changed, 126 insertions(+), 39 deletions(-) diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h index d0b1bc6..ca1fc38 100644 --- a/include/GL/internal/dri_interface.h +++ b/include/GL/internal/dri_interface.h @@ -270,7 +270,7 @@ struct __DRItexBufferExtensionRec { * Used by drivers that implement DRI2 */ #define __DRI2_FLUSH "DRI2_Flush" -#define __DRI2_FLUSH_VERSION 4 +#define __DRI2_FLUSH_VERSION 5 #define __DRI2_FLUSH_DRAWABLE (1 << 0) /* the drawable should be flushed. */ #define __DRI2_FLUSH_CONTEXT (1 << 1) /* glFlush should be called */ @@ -316,6 +316,16 @@ struct __DRI2flushExtensionRec { __DRIdrawable *drawable, unsigned flags, enum __DRI2throttleReason throttle_reason); + + /** + * Ask the driver to call getBuffers/getBuffersWithFormat on all + * surfaces on this screen before it starts rendering again. + * + * \param screen the screen to invalidate + * + * \since 5 + */ + void (*invalidateScreen)(__DRIscreen *screen); }; diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c index af388d9..88f634b 100644 --- a/src/glx/dri2_glx.c +++ b/src/glx/dri2_glx.c @@ -633,7 +633,7 @@ dri2_copy_drawable(struct dri2_drawable *priv, int dest, int src) } static void -dri2_wait_x(struct glx_context *gc) +__dri2_copy_x(struct glx_context *gc) { struct dri2_drawable *priv = (struct dri2_drawable *) GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); @@ -645,6 +645,18 @@ dri2_wait_x(struct glx_context *gc) } static void +dri2_wait_x(struct glx_context *gc) +{ + struct dri2_context *pcp = (struct dri2_context *) gc; + struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc; + + if (psc->f && psc->f->base.version >= 5 && psc->f->invalidateScreen) + psc->f->invalidateScreen(psc->driScreen); + else + __dri2_copy_x(gc); +} + +static void dri2_wait_gl(struct glx_context *gc) { struct dri2_drawable *priv = (struct dri2_drawable *) @@ -979,7 +991,7 @@ dri2InvalidateBuffers(Display *dpy, XID drawable) psc = (struct dri2_screen *) pdraw->psc; - if (pdraw && psc->f && psc->f->base.version >= 3 && psc->f->invalidate) + if (psc->f && psc->f->base.version >= 3 && psc->f->invalidate) psc->f->invalidate(pdp->driDrawable); } diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c index ca02e97..41257f9 100644 --- a/src/loader/loader_dri3_helper.c +++ b/src/loader/loader_dri3_helper.c @@ -113,6 +113,11 @@ loader_dri3_drawable_fini(struct loader_dri3_drawable *draw) dri3_free_render_buffer(draw, draw->buffers[i]); } + if (draw->sync_fence) { + xcb_sync_destroy_fence(draw->conn, draw->sync_fence); + xshmfence_unmap_shm(draw->shm_fence); + } + if (draw->special_event) { xcb_void_cookie_t cookie = xcb_present_select_input_checked(draw->conn, draw->eid, draw->drawable, @@ -549,7 +554,19 @@ loader_dri3_wait_x(struct loader_dri3_drawable *draw) struct loader_dri3_buffer *front; __DRIcontext *dri_context; - if (draw == NULL || !draw->have_fake_front) + if (draw == NULL) + return; + + if (draw->sync_fence) { + xshmfence_reset(draw->shm_fence); + + xcb_sync_trigger_fence(draw->conn, draw->sync_fence); + xcb_flush(draw->conn); + + xshmfence_await(draw->shm_fence); + } + + if (!draw->have_fake_front) return; front = dri3_fake_front_buffer(draw); @@ -943,6 +960,29 @@ no_shm_fence: return NULL; } +static void +dri3_attach_sync(struct loader_dri3_drawable *draw) +{ + int fence_fd; + + fence_fd = xshmfence_alloc_shm(); + if (fence_fd < 0) + return; + + draw->shm_fence = xshmfence_map_shm(fence_fd); + if (draw->shm_fence == NULL) { + close(fence_fd); + return; + } + + draw->sync_fence = xcb_generate_id(draw->conn); + xcb_dri3_fence_from_fd(draw->conn, + draw->drawable, + draw->sync_fence, + false, + fence_fd); +} + /** loader_dri3_update_drawable * * Called the first time we use the drawable and then @@ -1032,6 +1072,8 @@ dri3_update_drawable(__DRIdrawable *driDrawable, xcb_unregister_for_special_event(draw->conn, draw->special_event); draw->special_event = NULL; } + + dri3_attach_sync(draw); } dri3_flush_present_events(draw); return true; @@ -1375,6 +1417,15 @@ loader_dri3_get_buffers(__DRIdrawable *driDrawable, if (!front) return false; + + if (draw->sync_fence) { + xshmfence_reset(draw->shm_fence); + + xcb_sync_trigger_fence(draw->conn, draw->sync_fence); + xcb_flush(draw->conn); + + xshmfence_await(draw->shm_fence); + } } else { dri3_free_buffers(driDrawable, loader_dri3_buffer_front, draw); draw->have_fake_front = 0; diff --git a/src/loader/loader_dri3_helper.h b/src/loader/loader_dri3_helper.h index 1d1f15e..dab15b6 100644 --- a/src/loader/loader_dri3_helper.h +++ b/src/loader/loader_dri3_helper.h @@ -156,6 +156,9 @@ struct loader_dri3_drawable { xcb_gcontext_t gc; xcb_special_event_t *special_event; + xcb_sync_fence_t sync_fence; + struct xshmfence *shm_fence; + bool first_init; struct loader_dri3_extensions *ext; diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c index 79cb050..68fa0fe 100644 --- a/src/mesa/drivers/dri/common/dri_util.c +++ b/src/mesa/drivers/dri/common/dri_util.c @@ -805,6 +805,12 @@ dri2InvalidateDrawable(__DRIdrawable *drawable) drawable->dri2.stamp++; } +void +dri2InvalidateScreen(__DRIscreen *screen) +{ + screen->dri2.stamp++; +} + /** * Check that the gl_framebuffer associated with dPriv is the right size. * Resize the gl_framebuffer if needed. diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h index 6987f55..eb761d4 100644 --- a/src/mesa/drivers/dri/common/dri_util.h +++ b/src/mesa/drivers/dri/common/dri_util.h @@ -172,6 +172,7 @@ struct __DRIscreenRec { const __DRIdri2LoaderExtension *loader; const __DRIimageLookupExtension *image; const __DRIuseInvalidateExtension *useInvalidate; + unsigned int stamp; } dri2; struct { @@ -285,6 +286,9 @@ extern void dri2InvalidateDrawable(__DRIdrawable *drawable); extern void +dri2InvalidateScreen(__DRIscreen *screen); + +extern void driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv); extern void diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c index d6204fd..8ea17c3 100644 --- a/src/mesa/drivers/dri/i965/brw_context.c +++ b/src/mesa/drivers/dri/i965/brw_context.c @@ -1287,14 +1287,12 @@ intelMakeCurrent(__DRIcontext * driContextPriv, fb = _mesa_get_incomplete_framebuffer(); } else { fb = driDrawPriv->driverPrivate; - driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1; } if (driReadPriv == NULL) { readFb = _mesa_get_incomplete_framebuffer(); } else { readFb = driReadPriv->driverPrivate; - driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1; } /* The sRGB workaround changes the renderbuffer's format. We must change @@ -1382,11 +1380,6 @@ intel_update_dri2_buffers(struct brw_context *brw, __DRIdrawable *drawable) int i, count; const char *region_name; - /* Set this up front, so that in case our buffers get invalidated - * while we're getting new buffers, we don't clobber the stamp and - * thus ignore the invalidate. */ - drawable->lastStamp = drawable->dri2.stamp; - if (unlikely(INTEL_DEBUG & DEBUG_DRI)) fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable); @@ -1430,15 +1423,10 @@ intel_update_dri2_buffers(struct brw_context *brw, __DRIdrawable *drawable) } void -intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) +__intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) { + __DRIscreen *dri_screen = context->driScreenPriv; struct brw_context *brw = context->driverPrivate; - __DRIscreen *dri_screen = brw->screen->driScrnPriv; - - /* Set this up front, so that in case our buffers get invalidated - * while we're getting new buffers, we don't clobber the stamp and - * thus ignore the invalidate. */ - drawable->lastStamp = drawable->dri2.stamp; if (unlikely(INTEL_DEBUG & DEBUG_DRI)) fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable); @@ -1460,21 +1448,15 @@ intel_prepare_render(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; __DRIcontext *driContext = brw->driContext; - __DRIdrawable *drawable; - drawable = driContext->driDrawablePriv; - if (drawable && drawable->dri2.stamp != driContext->dri2.draw_stamp) { - if (drawable->lastStamp != drawable->dri2.stamp) - intel_update_renderbuffers(driContext, drawable); - driContext->dri2.draw_stamp = drawable->dri2.stamp; - } - - drawable = driContext->driReadablePriv; - if (drawable && drawable->dri2.stamp != driContext->dri2.read_stamp) { - if (drawable->lastStamp != drawable->dri2.stamp) - intel_update_renderbuffers(driContext, drawable); - driContext->dri2.read_stamp = drawable->dri2.stamp; - } + if (driContext->driDrawablePriv) + intel_update_renderbuffers(driContext, + driContext->driDrawablePriv, + false); + if (driContext->driReadablePriv) + intel_update_renderbuffers(driContext, + driContext->driReadablePriv, + false); /* If we're currently rendering to the front buffer, the rendering * that will happen next will probably dirty the front buffer. So diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index c92bb9f..42bd991 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -1354,8 +1354,27 @@ enum { DRI_CONF_BO_REUSE_ALL }; -void intel_update_renderbuffers(__DRIcontext *context, - __DRIdrawable *drawable); +void __intel_update_renderbuffers(__DRIcontext *context, + __DRIdrawable *drawable); +static inline void +intel_update_renderbuffers(__DRIcontext *context, + __DRIdrawable *drawable, + bool force) +{ + __DRIscreen *dri_screen = context->driScreenPriv; + unsigned int stamp = drawable->dri2.stamp + dri_screen->dri2.stamp; + + if (stamp == drawable->lastStamp && !force) + return; + + /* Set this up front, so that in case our buffers get invalidated + * while we're getting new buffers, we don't clobber the stamp and + * thus ignore the invalidate. */ + drawable->lastStamp = stamp; + + __intel_update_renderbuffers(context, drawable); +} + void intel_prepare_render(struct brw_context *brw); void intel_resolve_for_dri2_flush(struct brw_context *brw, diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c index e1c3c19..bb4a33e 100644 --- a/src/mesa/drivers/dri/i965/intel_screen.c +++ b/src/mesa/drivers/dri/i965/intel_screen.c @@ -207,11 +207,12 @@ intel_dri2_flush(__DRIdrawable *drawable) } static const struct __DRI2flushExtensionRec intelFlushExtension = { - .base = { __DRI2_FLUSH, 4 }, + .base = { __DRI2_FLUSH, 5 }, .flush = intel_dri2_flush, - .invalidate = dri2InvalidateDrawable, .flush_with_flags = intel_dri2_flush_with_flags, + .invalidate = dri2InvalidateDrawable, + .invalidateScreen = dri2InvalidateScreen, }; static struct intel_image_format intel_image_formats[] = { diff --git a/src/mesa/drivers/dri/i965/intel_tex_image.c b/src/mesa/drivers/dri/i965/intel_tex_image.c index 4454e53..f65a158 100644 --- a/src/mesa/drivers/dri/i965/intel_tex_image.c +++ b/src/mesa/drivers/dri/i965/intel_tex_image.c @@ -289,9 +289,8 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, if (!texObj) return; - if (dPriv->lastStamp != dPriv->dri2.stamp || - !pDRICtx->driScreenPriv->dri2.useInvalidate) - intel_update_renderbuffers(pDRICtx, dPriv); + intel_update_renderbuffers(pDRICtx, dPriv, + !pDRICtx->driScreenPriv->dri2.useInvalidate); rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); /* If the miptree isn't set, then intel_update_renderbuffers was unable -- 2.7.4