[Mesa-dev] [PATCH 1/3] gallium: add a pipe_context parameter to fence_finish

Nicolai Hähnle nhaehnle at gmail.com
Tue Aug 9 08:51:07 UTC 2016


Skimming through this, I wonder if PIPE_QUERY_GPU_FINISHED shouldn't use 
deferred fences. context.rst does say that it "does not imply 
serialization". But it only seems to be used by nine, and I'm not 
familiar with D3D expectations.

Anyway, this patch is

Reviewed-by: Nicolai Hähnle <nicolai.haehnle at amd.com>

On 06.08.2016 17:32, Marek Olšák wrote:
> From: Marek Olšák <marek.olsak at amd.com>
>
> required by glClientWaitSync (GL 4.5 Core spec) that can optionally flush
> the context
> ---
>  src/gallium/docs/source/context.rst              | 10 ++++------
>  src/gallium/drivers/ddebug/dd_draw.c             |  2 +-
>  src/gallium/drivers/ddebug/dd_screen.c           |  4 +++-
>  src/gallium/drivers/freedreno/freedreno_fence.c  |  5 +++--
>  src/gallium/drivers/freedreno/freedreno_fence.h  |  5 +++--
>  src/gallium/drivers/i915/i915_screen.c           |  1 +
>  src/gallium/drivers/ilo/ilo_screen.c             |  1 +
>  src/gallium/drivers/llvmpipe/lp_flush.c          |  3 ++-
>  src/gallium/drivers/llvmpipe/lp_screen.c         |  1 +
>  src/gallium/drivers/nouveau/nouveau_screen.c     |  1 +
>  src/gallium/drivers/r300/r300_screen.c           |  1 +
>  src/gallium/drivers/radeon/r600_pipe_common.c    |  1 +
>  src/gallium/drivers/radeon/r600_query.c          |  2 +-
>  src/gallium/drivers/rbug/rbug_screen.c           |  6 +++---
>  src/gallium/drivers/softpipe/sp_fence.c          |  1 +
>  src/gallium/drivers/softpipe/sp_flush.c          |  2 +-
>  src/gallium/drivers/svga/svga_context.c          |  4 ++--
>  src/gallium/drivers/svga/svga_screen.c           |  1 +
>  src/gallium/drivers/swr/swr_context.cpp          |  4 ++--
>  src/gallium/drivers/swr/swr_draw.cpp             |  2 +-
>  src/gallium/drivers/swr/swr_fence.cpp            |  1 +
>  src/gallium/drivers/swr/swr_fence.h              |  1 +
>  src/gallium/drivers/swr/swr_query.cpp            |  4 ++--
>  src/gallium/drivers/swr/swr_screen.cpp           |  6 +++---
>  src/gallium/drivers/swr/swr_state.cpp            |  2 +-
>  src/gallium/drivers/trace/tr_screen.c            |  5 ++++-
>  src/gallium/drivers/vc4/vc4_fence.c              |  1 +
>  src/gallium/drivers/virgl/virgl_screen.c         |  1 +
>  src/gallium/include/pipe/p_screen.h              | 15 ++++++++++++---
>  src/gallium/state_trackers/clover/core/event.cpp |  4 ++--
>  src/gallium/state_trackers/dri/dri2.c            |  6 +++---
>  src/gallium/state_trackers/dri/dri_drawable.c    |  2 +-
>  src/gallium/state_trackers/glx/xlib/xm_api.c     |  2 +-
>  src/gallium/state_trackers/nine/swapchain9.c     |  6 +++---
>  src/gallium/state_trackers/vdpau/presentation.c  |  4 ++--
>  src/gallium/state_trackers/xa/xa_context.c       |  2 +-
>  src/gallium/state_trackers/xvmc/surface.c        |  2 +-
>  src/mesa/state_tracker/st_cb_flush.c             |  2 +-
>  src/mesa/state_tracker/st_cb_syncobj.c           |  4 ++--
>  39 files changed, 77 insertions(+), 50 deletions(-)
>
> diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst
> index e646ea0..af3d266 100644
> --- a/src/gallium/docs/source/context.rst
> +++ b/src/gallium/docs/source/context.rst
> @@ -459,26 +459,24 @@ processed even where they're known to be obscured.
>
>
>  Flushing
>  ^^^^^^^^
>
>  ``flush``
>
>  PIPE_FLUSH_END_OF_FRAME: Whether the flush marks the end of frame.
>
>  PIPE_FLUSH_DEFERRED: It is not required to flush right away, but it is required
> -to return a valid fence. The behavior of fence_finish or any other call isn't
> -changed. The only side effect can be that fence_finish will wait a little
> -longer. No guidance is given as to how drivers should implement fence_finish
> -with deferred flushes. If some drivers can't do deferred flushes safely, they
> -should just ignore the flag.
> -
> +to return a valid fence. If fence_finish is called with the returned fence
> +and the context is still unflushed, and the ctx parameter of fence_finish is
> +equal to the context where the fence was created, fence_finish will flush
> +the context.
>
>
>  ``flush_resource``
>
>  Flush the resource cache, so that the resource can be used
>  by an external client. Possible usage:
>  - flushing a resource before presenting it on the screen
>  - flushing a resource if some other process or device wants to use it
>  This shouldn't be used to flush caches if the resource is only managed
>  by a single pipe_screen and is not shared with another process.
> diff --git a/src/gallium/drivers/ddebug/dd_draw.c b/src/gallium/drivers/ddebug/dd_draw.c
> index c1bfdaf..97325e4 100644
> --- a/src/gallium/drivers/ddebug/dd_draw.c
> +++ b/src/gallium/drivers/ddebug/dd_draw.c
> @@ -541,21 +541,21 @@ dd_flush_and_check_hang(struct dd_context *dctx,
>     bool idle;
>
>     assert(timeout_ms > 0);
>
>     pipe->flush(pipe, &fence, flush_flags);
>     if (flush_fence)
>        screen->fence_reference(screen, flush_fence, fence);
>     if (!fence)
>        return false;
>
> -   idle = screen->fence_finish(screen, fence, timeout_ms * 1000000);
> +   idle = screen->fence_finish(screen, NULL, fence, timeout_ms * 1000000);
>     screen->fence_reference(screen, &fence, NULL);
>     if (!idle)
>        fprintf(stderr, "dd: GPU hang detected!\n");
>     return !idle;
>  }
>
>  static void
>  dd_flush_and_handle_hang(struct dd_context *dctx,
>                           struct pipe_fence_handle **fence, unsigned flags,
>                           const char *cause)
> diff --git a/src/gallium/drivers/ddebug/dd_screen.c b/src/gallium/drivers/ddebug/dd_screen.c
> index 412ea36..3deba0a 100644
> --- a/src/gallium/drivers/ddebug/dd_screen.c
> +++ b/src/gallium/drivers/ddebug/dd_screen.c
> @@ -256,26 +256,28 @@ dd_screen_fence_reference(struct pipe_screen *_screen,
>                            struct pipe_fence_handle **pdst,
>                            struct pipe_fence_handle *src)
>  {
>     struct pipe_screen *screen = dd_screen(_screen)->screen;
>
>     screen->fence_reference(screen, pdst, src);
>  }
>
>  static boolean
>  dd_screen_fence_finish(struct pipe_screen *_screen,
> +                       struct pipe_context *_ctx,
>                         struct pipe_fence_handle *fence,
>                         uint64_t timeout)
>  {
>     struct pipe_screen *screen = dd_screen(_screen)->screen;
> +   struct pipe_context *ctx = _ctx ? dd_context(_ctx)->pipe : NULL;
>
> -   return screen->fence_finish(screen, fence, timeout);
> +   return screen->fence_finish(screen, ctx, fence, timeout);
>  }
>
>
>  /********************************************************************
>   * screen
>   */
>
>  static void
>  dd_screen_destroy(struct pipe_screen *_screen)
>  {
> diff --git a/src/gallium/drivers/freedreno/freedreno_fence.c b/src/gallium/drivers/freedreno/freedreno_fence.c
> index 5125f09..a60da1c 100644
> --- a/src/gallium/drivers/freedreno/freedreno_fence.c
> +++ b/src/gallium/drivers/freedreno/freedreno_fence.c
> @@ -44,22 +44,23 @@ fd_screen_fence_ref(struct pipe_screen *pscreen,
>  		struct pipe_fence_handle **ptr,
>  		struct pipe_fence_handle *pfence)
>  {
>  	if (pipe_reference(&(*ptr)->reference, &pfence->reference))
>  		FREE(*ptr);
>
>  	*ptr = pfence;
>  }
>
>  boolean fd_screen_fence_finish(struct pipe_screen *screen,
> -		struct pipe_fence_handle *fence,
> -		uint64_t timeout)
> +			       struct pipe_context *ctx,
> +			       struct pipe_fence_handle *fence,
> +			       uint64_t timeout)
>  {
>  	if (fd_pipe_wait_timeout(fence->screen->pipe, fence->timestamp, timeout))
>  		return false;
>
>  	return true;
>  }
>
>  struct pipe_fence_handle * fd_fence_create(struct pipe_context *pctx,
>  		uint32_t timestamp)
>  {
> diff --git a/src/gallium/drivers/freedreno/freedreno_fence.h b/src/gallium/drivers/freedreno/freedreno_fence.h
> index 06c314a..e0a5899 100644
> --- a/src/gallium/drivers/freedreno/freedreno_fence.h
> +++ b/src/gallium/drivers/freedreno/freedreno_fence.h
> @@ -28,16 +28,17 @@
>
>  #ifndef FREEDRENO_FENCE_H_
>  #define FREEDRENO_FENCE_H_
>
>  #include "pipe/p_context.h"
>
>  void fd_screen_fence_ref(struct pipe_screen *pscreen,
>  		struct pipe_fence_handle **ptr,
>  		struct pipe_fence_handle *pfence);
>  boolean fd_screen_fence_finish(struct pipe_screen *screen,
> -		struct pipe_fence_handle *pfence,
> -		uint64_t timeout);
> +			       struct pipe_context *ctx,
> +			       struct pipe_fence_handle *pfence,
> +			       uint64_t timeout);
>  struct pipe_fence_handle * fd_fence_create(struct pipe_context *pctx,
>  		uint32_t timestamp);
>
>  #endif /* FREEDRENO_FENCE_H_ */
> diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c
> index 6b5218b..ab3d4a6 100644
> --- a/src/gallium/drivers/i915/i915_screen.c
> +++ b/src/gallium/drivers/i915/i915_screen.c
> @@ -493,20 +493,21 @@ i915_fence_reference(struct pipe_screen *screen,
>                       struct pipe_fence_handle **ptr,
>                       struct pipe_fence_handle *fence)
>  {
>     struct i915_screen *is = i915_screen(screen);
>
>     is->iws->fence_reference(is->iws, ptr, fence);
>  }
>
>  static boolean
>  i915_fence_finish(struct pipe_screen *screen,
> +                  struct pipe_context *ctx,
>                    struct pipe_fence_handle *fence,
>                    uint64_t timeout)
>  {
>     struct i915_screen *is = i915_screen(screen);
>
>     if (!timeout)
>        return is->iws->fence_signalled(is->iws, fence) == 1;
>
>     return is->iws->fence_finish(is->iws, fence) == 1;
>  }
> diff --git a/src/gallium/drivers/ilo/ilo_screen.c b/src/gallium/drivers/ilo/ilo_screen.c
> index 448f512..e98b6f2 100644
> --- a/src/gallium/drivers/ilo/ilo_screen.c
> +++ b/src/gallium/drivers/ilo/ilo_screen.c
> @@ -689,20 +689,21 @@ ilo_screen_fence_reference(struct pipe_screen *screen,
>
>     STATIC_ASSERT(&((struct pipe_fence_handle *) NULL)->reference == NULL);
>     if (pipe_reference(&old->reference, &fence->reference)) {
>        intel_bo_unref(old->seqno_bo);
>        FREE(old);
>     }
>  }
>
>  static boolean
>  ilo_screen_fence_finish(struct pipe_screen *screen,
> +                        struct pipe_context *ctx,
>                          struct pipe_fence_handle *fence,
>                          uint64_t timeout)
>  {
>     const int64_t wait_timeout = (timeout > INT64_MAX) ? -1 : timeout;
>     bool signaled;
>
>     signaled = (!fence->seqno_bo ||
>           intel_bo_wait(fence->seqno_bo, wait_timeout) == 0);
>
>     /* XXX not thread safe */
> diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c
> index 241c2cc..452753f 100644
> --- a/src/gallium/drivers/llvmpipe/lp_flush.c
> +++ b/src/gallium/drivers/llvmpipe/lp_flush.c
> @@ -75,21 +75,22 @@ llvmpipe_flush( struct pipe_context *pipe,
>     }
>  }
>
>  void
>  llvmpipe_finish( struct pipe_context *pipe,
>                   const char *reason )
>  {
>     struct pipe_fence_handle *fence = NULL;
>     llvmpipe_flush(pipe, &fence, reason);
>     if (fence) {
> -      pipe->screen->fence_finish(pipe->screen, fence, PIPE_TIMEOUT_INFINITE);
> +      pipe->screen->fence_finish(pipe->screen, NULL, fence,
> +                                 PIPE_TIMEOUT_INFINITE);
>        pipe->screen->fence_reference(pipe->screen, &fence, NULL);
>     }
>  }
>
>  /**
>   * Flush context if necessary.
>   *
>   * Returns FALSE if it would have block, but do_not_block was set, TRUE
>   * otherwise.
>   *
> diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c
> index 61c3fb7..1c00aa9 100644
> --- a/src/gallium/drivers/llvmpipe/lp_screen.c
> +++ b/src/gallium/drivers/llvmpipe/lp_screen.c
> @@ -565,20 +565,21 @@ llvmpipe_fence_reference(struct pipe_screen *screen,
>
>     lp_fence_reference(old, f);
>  }
>
>
>  /**
>   * Wait for the fence to finish.
>   */
>  static boolean
>  llvmpipe_fence_finish(struct pipe_screen *screen,
> +                      struct pipe_context *ctx,
>                        struct pipe_fence_handle *fence_handle,
>                        uint64_t timeout)
>  {
>     struct lp_fence *f = (struct lp_fence *) fence_handle;
>
>     if (!timeout)
>        return lp_fence_signalled(f);
>
>     lp_fence_wait(f);
>     return TRUE;
> diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c
> index 2c421cc..f59e101 100644
> --- a/src/gallium/drivers/nouveau/nouveau_screen.c
> +++ b/src/gallium/drivers/nouveau/nouveau_screen.c
> @@ -63,20 +63,21 @@ nouveau_screen_get_timestamp(struct pipe_screen *pscreen)
>  static void
>  nouveau_screen_fence_ref(struct pipe_screen *pscreen,
>                           struct pipe_fence_handle **ptr,
>                           struct pipe_fence_handle *pfence)
>  {
>     nouveau_fence_ref(nouveau_fence(pfence), (struct nouveau_fence **)ptr);
>  }
>
>  static boolean
>  nouveau_screen_fence_finish(struct pipe_screen *screen,
> +                            struct pipe_context *ctx,
>                              struct pipe_fence_handle *pfence,
>                              uint64_t timeout)
>  {
>     if (!timeout)
>        return nouveau_fence_signalled(nouveau_fence(pfence));
>
>     return nouveau_fence_wait(nouveau_fence(pfence), NULL);
>  }
>
>
> diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
> index 7d2ea4a..b69e524 100644
> --- a/src/gallium/drivers/r300/r300_screen.c
> +++ b/src/gallium/drivers/r300/r300_screen.c
> @@ -691,20 +691,21 @@ static void r300_destroy_screen(struct pipe_screen* pscreen)
>  static void r300_fence_reference(struct pipe_screen *screen,
>                                   struct pipe_fence_handle **ptr,
>                                   struct pipe_fence_handle *fence)
>  {
>      struct radeon_winsys *rws = r300_screen(screen)->rws;
>
>      rws->fence_reference(ptr, fence);
>  }
>
>  static boolean r300_fence_finish(struct pipe_screen *screen,
> +                                 struct pipe_context *ctx,
>                                   struct pipe_fence_handle *fence,
>                                   uint64_t timeout)
>  {
>      struct radeon_winsys *rws = r300_screen(screen)->rws;
>
>      return rws->fence_wait(rws, fence, timeout);
>  }
>
>  struct pipe_screen* r300_screen_create(struct radeon_winsys *rws)
>  {
> diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
> index 7fd3fe0..119fdf5 100644
> --- a/src/gallium/drivers/radeon/r600_pipe_common.c
> +++ b/src/gallium/drivers/radeon/r600_pipe_common.c
> @@ -947,20 +947,21 @@ static void r600_fence_reference(struct pipe_screen *screen,
>
>  	if (pipe_reference(&(*rdst)->reference, &rsrc->reference)) {
>  		ws->fence_reference(&(*rdst)->gfx, NULL);
>  		ws->fence_reference(&(*rdst)->sdma, NULL);
>  		FREE(*rdst);
>  	}
>          *rdst = rsrc;
>  }
>
>  static boolean r600_fence_finish(struct pipe_screen *screen,
> +				 struct pipe_context *ctx,
>  				 struct pipe_fence_handle *fence,
>  				 uint64_t timeout)
>  {
>  	struct radeon_winsys *rws = ((struct r600_common_screen*)screen)->ws;
>  	struct r600_multi_fence *rfence = (struct r600_multi_fence *)fence;
>  	int64_t abs_timeout = os_time_get_absolute_timeout(timeout);
>
>  	if (rfence->sdma) {
>  		if (!rws->fence_wait(rws, rfence->sdma, timeout))
>  			return false;
> diff --git a/src/gallium/drivers/radeon/r600_query.c b/src/gallium/drivers/radeon/r600_query.c
> index f6a65a6..c203439 100644
> --- a/src/gallium/drivers/radeon/r600_query.c
> +++ b/src/gallium/drivers/radeon/r600_query.c
> @@ -202,21 +202,21 @@ static bool r600_query_sw_get_result(struct r600_common_context *rctx,
>
>  	switch (query->b.type) {
>  	case PIPE_QUERY_TIMESTAMP_DISJOINT:
>  		/* Convert from cycles per millisecond to cycles per second (Hz). */
>  		result->timestamp_disjoint.frequency =
>  			(uint64_t)rctx->screen->info.clock_crystal_freq * 1000;
>  		result->timestamp_disjoint.disjoint = false;
>  		return true;
>  	case PIPE_QUERY_GPU_FINISHED: {
>  		struct pipe_screen *screen = rctx->b.screen;
> -		result->b = screen->fence_finish(screen, query->fence,
> +		result->b = screen->fence_finish(screen, NULL, query->fence,
>  						 wait ? PIPE_TIMEOUT_INFINITE : 0);
>  		return result->b;
>  	}
>
>  	case R600_QUERY_GPIN_ASIC_ID:
>  		result->u32 = 0;
>  		return true;
>  	case R600_QUERY_GPIN_NUM_SIMD:
>  		result->u32 = rctx->screen->info.num_good_compute_units;
>  		return true;
> diff --git a/src/gallium/drivers/rbug/rbug_screen.c b/src/gallium/drivers/rbug/rbug_screen.c
> index c2950e4..8d21669 100644
> --- a/src/gallium/drivers/rbug/rbug_screen.c
> +++ b/src/gallium/drivers/rbug/rbug_screen.c
> @@ -222,29 +222,29 @@ rbug_screen_fence_reference(struct pipe_screen *_screen,
>     struct rbug_screen *rb_screen = rbug_screen(_screen);
>     struct pipe_screen *screen = rb_screen->screen;
>
>     screen->fence_reference(screen,
>                             ptr,
>                             fence);
>  }
>
>  static boolean
>  rbug_screen_fence_finish(struct pipe_screen *_screen,
> +                         struct pipe_context *_ctx,
>                           struct pipe_fence_handle *fence,
>                           uint64_t timeout)
>  {
>     struct rbug_screen *rb_screen = rbug_screen(_screen);
>     struct pipe_screen *screen = rb_screen->screen;
> +   struct pipe_context *ctx = _ctx ? rbug_context(_ctx)->pipe : NULL;
>
> -   return screen->fence_finish(screen,
> -                               fence,
> -                               timeout);
> +   return screen->fence_finish(screen, ctx, fence, timeout);
>  }
>
>  boolean
>  rbug_enabled()
>  {
>     return debug_get_option_rbug();
>  }
>
>  struct pipe_screen *
>  rbug_screen_create(struct pipe_screen *screen)
> diff --git a/src/gallium/drivers/softpipe/sp_fence.c b/src/gallium/drivers/softpipe/sp_fence.c
> index 6168236..1861b0d 100644
> --- a/src/gallium/drivers/softpipe/sp_fence.c
> +++ b/src/gallium/drivers/softpipe/sp_fence.c
> @@ -35,20 +35,21 @@ static void
>  softpipe_fence_reference(struct pipe_screen *screen,
>                           struct pipe_fence_handle **ptr,
>                           struct pipe_fence_handle *fence)
>  {
>     *ptr = fence;
>  }
>
>
>  static boolean
>  softpipe_fence_finish(struct pipe_screen *screen,
> +                      struct pipe_context *ctx,
>                        struct pipe_fence_handle *fence,
>                        uint64_t timeout)
>  {
>     assert(fence);
>     return TRUE;
>  }
>
>
>  void
>  softpipe_init_screen_fence_funcs(struct pipe_screen *screen)
> diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c
> index 29fcf7f..656d8a3 100644
> --- a/src/gallium/drivers/softpipe/sp_flush.c
> +++ b/src/gallium/drivers/softpipe/sp_flush.c
> @@ -146,21 +146,21 @@ softpipe_flush_resource(struct pipe_context *pipe,
>           if (do_not_block)
>              return FALSE;
>
>           softpipe_flush(pipe, flush_flags, &fence);
>
>           if (fence) {
>              /*
>               * This is for illustrative purposes only, as softpipe does not
>               * have fences.
>               */
> -            pipe->screen->fence_finish(pipe->screen, fence,
> +            pipe->screen->fence_finish(pipe->screen, NULL, fence,
>                                         PIPE_TIMEOUT_INFINITE);

It would also make sense to pass the context here.


>              pipe->screen->fence_reference(pipe->screen, &fence, NULL);
>           }
>        } else {
>           /*
>            * Just flush.
>            */
>
>           softpipe_flush(pipe, flush_flags, NULL);
>        }
> diff --git a/src/gallium/drivers/svga/svga_context.c b/src/gallium/drivers/svga/svga_context.c
> index c7f4aae..f623caf 100644
> --- a/src/gallium/drivers/svga/svga_context.c
> +++ b/src/gallium/drivers/svga/svga_context.c
> @@ -341,42 +341,42 @@ void svga_context_flush( struct svga_context *svga,
>        svga->rebind.flags.fs = TRUE;
>        svga->rebind.flags.gs = TRUE;
>
>        if (svga_need_to_rebind_resources(svga)) {
>           svga->rebind.flags.query = TRUE;
>        }
>     }
>
>     if (SVGA_DEBUG & DEBUG_SYNC) {
>        if (fence)
> -         svga->pipe.screen->fence_finish( svga->pipe.screen, fence,
> +         svga->pipe.screen->fence_finish( svga->pipe.screen, NULL, fence,
>                                            PIPE_TIMEOUT_INFINITE);
>     }
>
>     if (pfence)
>        svgascreen->sws->fence_reference(svgascreen->sws, pfence, fence);
>
>     svgascreen->sws->fence_reference(svgascreen->sws, &fence, NULL);
>  }
>
>
>  /**
>   * Flush pending commands and wait for completion with a fence.
>   */
>  void
>  svga_context_finish(struct svga_context *svga)
>  {
>     struct pipe_screen *screen = svga->pipe.screen;
>     struct pipe_fence_handle *fence = NULL;
>
>     svga_context_flush(svga, &fence);
> -   screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
> +   screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);
>     screen->fence_reference(screen, &fence, NULL);
>  }
>
>
>  /**
>   * Emit pending drawing commands to the command buffer.
>   * If the command buffer overflows, we flush it and retry.
>   * \sa svga_hwtnl_flush()
>   */
>  void svga_hwtnl_flush_retry( struct svga_context *svga )
> diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c
> index 13253ac..7c4e305 100644
> --- a/src/gallium/drivers/svga/svga_screen.c
> +++ b/src/gallium/drivers/svga/svga_screen.c
> @@ -797,20 +797,21 @@ svga_fence_reference(struct pipe_screen *screen,
>                       struct pipe_fence_handle **ptr,
>                       struct pipe_fence_handle *fence)
>  {
>     struct svga_winsys_screen *sws = svga_screen(screen)->sws;
>     sws->fence_reference(sws, ptr, fence);
>  }
>
>
>  static boolean
>  svga_fence_finish(struct pipe_screen *screen,
> +                  struct pipe_context *ctx,
>                    struct pipe_fence_handle *fence,
>                    uint64_t timeout)
>  {
>     struct svga_winsys_screen *sws = svga_screen(screen)->sws;
>
>     if (!timeout)
>        return sws->fence_signalled(sws, fence, 0) == 0;
>
>     SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "%s fence_ptr %p\n",
>              __FUNCTION__, fence);
> diff --git a/src/gallium/drivers/swr/swr_context.cpp b/src/gallium/drivers/swr/swr_context.cpp
> index 1083c9d..835c353 100644
> --- a/src/gallium/drivers/swr/swr_context.cpp
> +++ b/src/gallium/drivers/swr/swr_context.cpp
> @@ -121,21 +121,21 @@ swr_transfer_map(struct pipe_context *pipe,
>        if (usage & PIPE_TRANSFER_DONTBLOCK) {
>           if (swr_is_fence_pending(screen->flush_fence))
>              return NULL;
>        } else {
>           if (spr->status) {
>              /* But, if there's no fence pending, submit one.
>               * XXX: Remove once draw timestamps are finished. */
>              if (!swr_is_fence_pending(screen->flush_fence))
>                 swr_fence_submit(swr_context(pipe), screen->flush_fence);
>
> -            swr_fence_finish(pipe->screen, screen->flush_fence, 0);
> +            swr_fence_finish(pipe->screen, NULL, screen->flush_fence, 0);
>              swr_resource_unused(resource);
>           }
>        }
>     }
>
>     pt = CALLOC_STRUCT(pipe_transfer);
>     if (!pt)
>        return NULL;
>     pipe_resource_reference(&pt->resource, resource);
>     pt->level = level;
> @@ -198,21 +198,21 @@ swr_resource_copy(struct pipe_context *pipe,
>                    struct pipe_resource *src,
>                    unsigned src_level,
>                    const struct pipe_box *src_box)
>  {
>     struct swr_screen *screen = swr_screen(pipe->screen);
>
>     /* If either the src or dst is a renderTarget, store tiles before copy */
>     swr_store_dirty_resource(pipe, src, SWR_TILE_RESOLVED);
>     swr_store_dirty_resource(pipe, dst, SWR_TILE_RESOLVED);
>
> -   swr_fence_finish(pipe->screen, screen->flush_fence, 0);
> +   swr_fence_finish(pipe->screen, NULL, screen->flush_fence, 0);
>     swr_resource_unused(src);
>     swr_resource_unused(dst);
>
>     if ((dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER)
>         || (dst->target != PIPE_BUFFER && src->target != PIPE_BUFFER)) {
>        util_resource_copy_region(
>           pipe, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box);
>        return;
>     }
>
> diff --git a/src/gallium/drivers/swr/swr_draw.cpp b/src/gallium/drivers/swr/swr_draw.cpp
> index ab8d275..0f6a8c6 100644
> --- a/src/gallium/drivers/swr/swr_draw.cpp
> +++ b/src/gallium/drivers/swr/swr_draw.cpp
> @@ -232,21 +232,21 @@ swr_flush(struct pipe_context *pipe,
>     if (fence)
>        swr_fence_reference(pipe->screen, fence, screen->flush_fence);
>  }
>
>  void
>  swr_finish(struct pipe_context *pipe)
>  {
>     struct pipe_fence_handle *fence = nullptr;
>
>     swr_flush(pipe, &fence, 0);
> -   swr_fence_finish(pipe->screen, fence, 0);
> +   swr_fence_finish(pipe->screen, NULL, fence, 0);
>     swr_fence_reference(pipe->screen, &fence, NULL);
>  }
>
>
>  /*
>   * Store SWR HotTiles back to renderTarget surface.
>   */
>  void
>  swr_store_render_target(struct pipe_context *pipe,
>                          uint32_t attachment,
> diff --git a/src/gallium/drivers/swr/swr_fence.cpp b/src/gallium/drivers/swr/swr_fence.cpp
> index 8a8e864..7fe2470 100644
> --- a/src/gallium/drivers/swr/swr_fence.cpp
> +++ b/src/gallium/drivers/swr/swr_fence.cpp
> @@ -104,20 +104,21 @@ swr_fence_reference(struct pipe_screen *screen,
>     if (pipe_reference(&old->reference, &fence->reference))
>        swr_fence_destroy(old);
>  }
>
>
>  /*
>   * Wait for the fence to finish.
>   */
>  boolean
>  swr_fence_finish(struct pipe_screen *screen,
> +                 struct pipe_context *ctx,
>                   struct pipe_fence_handle *fence_handle,
>                   uint64_t timeout)
>  {
>     while (!swr_is_fence_done(fence_handle))
>        sched_yield();
>
>     swr_fence(fence_handle)->pending = FALSE;
>
>     return TRUE;
>  }
> diff --git a/src/gallium/drivers/swr/swr_fence.h b/src/gallium/drivers/swr/swr_fence.h
> index 47f4d2e..80a4345 100644
> --- a/src/gallium/drivers/swr/swr_fence.h
> +++ b/src/gallium/drivers/swr/swr_fence.h
> @@ -62,19 +62,20 @@ swr_is_fence_pending(struct pipe_fence_handle *fence_handle)
>
>  void swr_fence_init(struct pipe_screen *screen);
>
>  struct pipe_fence_handle *swr_fence_create();
>
>  void swr_fence_reference(struct pipe_screen *screen,
>                           struct pipe_fence_handle **ptr,
>                           struct pipe_fence_handle *f);
>
>  boolean swr_fence_finish(struct pipe_screen *screen,
> +                         struct pipe_context *ctx,
>                           struct pipe_fence_handle *fence_handle,
>                           uint64_t timeout);
>
>  void
>  swr_fence_submit(struct swr_context *ctx, struct pipe_fence_handle *fence);
>
>  uint64_t swr_get_timestamp(struct pipe_screen *screen);
>
>  #endif
> diff --git a/src/gallium/drivers/swr/swr_query.cpp b/src/gallium/drivers/swr/swr_query.cpp
> index 7867db3..5b8f059 100644
> --- a/src/gallium/drivers/swr/swr_query.cpp
> +++ b/src/gallium/drivers/swr/swr_query.cpp
> @@ -56,21 +56,21 @@ swr_create_query(struct pipe_context *pipe, unsigned type, unsigned index)
>  }
>
>
>  static void
>  swr_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
>  {
>     struct swr_query *pq = swr_query(q);
>
>     if (pq->fence) {
>        if (swr_is_fence_pending(pq->fence))
> -         swr_fence_finish(pipe->screen, pq->fence, 0);
> +         swr_fence_finish(pipe->screen, NULL, pq->fence, 0);
>        swr_fence_reference(pipe->screen, &pq->fence, NULL);
>     }
>
>     FREE(pq);
>  }
>
>
>  static void
>  swr_gather_stats(struct pipe_context *pipe, struct swr_query *pq)
>  {
> @@ -121,21 +121,21 @@ swr_get_query_result(struct pipe_context *pipe,
>  {
>     struct swr_query *pq = swr_query(q);
>     struct swr_query_result *start = &pq->start;
>     struct swr_query_result *end = &pq->end;
>     unsigned index = pq->index;
>
>     if (pq->fence) {
>        if (!wait && !swr_is_fence_done(pq->fence))
>           return FALSE;
>
> -      swr_fence_finish(pipe->screen, pq->fence, 0);
> +      swr_fence_finish(pipe->screen, NULL, pq->fence, 0);
>        swr_fence_reference(pipe->screen, &pq->fence, NULL);
>     }
>
>     /* XXX: Need to handle counter rollover */
>
>     switch (pq->type) {
>     /* Booleans */
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
>        result->b = end->core.DepthPassCount != start->core.DepthPassCount;
>        break;
> diff --git a/src/gallium/drivers/swr/swr_screen.cpp b/src/gallium/drivers/swr/swr_screen.cpp
> index e0e59fa..df44967 100644
> --- a/src/gallium/drivers/swr/swr_screen.cpp
> +++ b/src/gallium/drivers/swr/swr_screen.cpp
> @@ -650,21 +650,21 @@ swr_resource_destroy(struct pipe_screen *p_screen, struct pipe_resource *pt)
>     struct swr_resource *spr = swr_resource(pt);
>     struct pipe_context *pipe = screen->pipe;
>
>     /* Only wait on fence if the resource is being used */
>     if (pipe && spr->status) {
>        /* But, if there's no fence pending, submit one.
>         * XXX: Remove once draw timestamps are implmented. */
>        if (!swr_is_fence_pending(screen->flush_fence))
>           swr_fence_submit(swr_context(pipe), screen->flush_fence);
>
> -      swr_fence_finish(p_screen, screen->flush_fence, 0);
> +      swr_fence_finish(p_screen, NULL, screen->flush_fence, 0);
>        swr_resource_unused(pt);
>     }
>
>     /*
>      * Free resource primary surface.  If resource is display target, winsys
>      * manages the buffer and will free it on displaytarget_destroy.
>      */
>     if (spr->display_target) {
>        /* display target */
>        struct sw_winsys *winsys = screen->winsys;
> @@ -685,41 +685,41 @@ swr_flush_frontbuffer(struct pipe_screen *p_screen,
>                        unsigned layer,
>                        void *context_private,
>                        struct pipe_box *sub_box)
>  {
>     struct swr_screen *screen = swr_screen(p_screen);
>     struct sw_winsys *winsys = screen->winsys;
>     struct swr_resource *spr = swr_resource(resource);
>     struct pipe_context *pipe = screen->pipe;
>
>     if (pipe) {
> -      swr_fence_finish(p_screen, screen->flush_fence, 0);
> +      swr_fence_finish(p_screen, NULL, screen->flush_fence, 0);
>        swr_resource_unused(resource);
>        SwrEndFrame(swr_context(pipe)->swrContext);
>     }
>
>     debug_assert(spr->display_target);
>     if (spr->display_target)
>        winsys->displaytarget_display(
>           winsys, spr->display_target, context_private, sub_box);
>  }
>
>
>  static void
>  swr_destroy_screen(struct pipe_screen *p_screen)
>  {
>     struct swr_screen *screen = swr_screen(p_screen);
>     struct sw_winsys *winsys = screen->winsys;
>
>     fprintf(stderr, "SWR destroy screen!\n");
>
> -   swr_fence_finish(p_screen, screen->flush_fence, 0);
> +   swr_fence_finish(p_screen, NULL, screen->flush_fence, 0);
>     swr_fence_reference(p_screen, &screen->flush_fence, NULL);
>
>     JitDestroyContext(screen->hJitMgr);
>
>     if (winsys->destroy)
>        winsys->destroy(winsys);
>
>     FREE(screen);
>  }
>
> diff --git a/src/gallium/drivers/swr/swr_state.cpp b/src/gallium/drivers/swr/swr_state.cpp
> index dac95ce..2df7985 100644
> --- a/src/gallium/drivers/swr/swr_state.cpp
> +++ b/src/gallium/drivers/swr/swr_state.cpp
> @@ -1383,21 +1383,21 @@ swr_update_derived(struct pipe_context *pipe,
>     backendState.constantInterpolationMask =
>        ctx->rasterizer->flatshade ?
>        ctx->fs->flatConstantMask :
>        ctx->fs->constantMask;
>     backendState.pointSpriteTexCoordMask = ctx->fs->pointSpriteMask;
>
>     SwrSetBackendState(ctx->swrContext, &backendState);
>
>     /* Ensure that any in-progress attachment change StoreTiles finish */
>     if (swr_is_fence_pending(screen->flush_fence))
> -      swr_fence_finish(pipe->screen, screen->flush_fence, 0);
> +      swr_fence_finish(pipe->screen, NULL, screen->flush_fence, 0);
>
>     /* Finally, update the in-use status of all resources involved in draw */
>     swr_update_resource_status(pipe, p_draw_info);
>
>     ctx->dirty = post_update_dirty_flags;
>  }
>
>
>  static struct pipe_stream_output_target *
>  swr_create_so_target(struct pipe_context *pipe,
> diff --git a/src/gallium/drivers/trace/tr_screen.c b/src/gallium/drivers/trace/tr_screen.c
> index 260f1df..67241ca 100644
> --- a/src/gallium/drivers/trace/tr_screen.c
> +++ b/src/gallium/drivers/trace/tr_screen.c
> @@ -395,34 +395,37 @@ trace_screen_fence_reference(struct pipe_screen *_screen,
>     trace_dump_arg(ptr, src);
>
>     screen->fence_reference(screen, pdst, src);
>
>     trace_dump_call_end();
>  }
>
>
>  static boolean
>  trace_screen_fence_finish(struct pipe_screen *_screen,
> +                          struct pipe_context *_ctx,
>                            struct pipe_fence_handle *fence,
>                            uint64_t timeout)
>  {
>     struct trace_screen *tr_scr = trace_screen(_screen);
>     struct pipe_screen *screen = tr_scr->screen;
> +   struct pipe_context *ctx = _ctx ? trace_context(_ctx)->pipe : NULL;
>     int result;
>
>     trace_dump_call_begin("pipe_screen", "fence_finish");
>
>     trace_dump_arg(ptr, screen);
> +   trace_dump_arg(ptr, ctx);
>     trace_dump_arg(ptr, fence);
>     trace_dump_arg(uint, timeout);
>
> -   result = screen->fence_finish(screen, fence, timeout);
> +   result = screen->fence_finish(screen, ctx, fence, timeout);
>
>     trace_dump_ret(bool, result);
>
>     trace_dump_call_end();
>
>     return result;
>  }
>
>
>  /********************************************************************
> diff --git a/src/gallium/drivers/vc4/vc4_fence.c b/src/gallium/drivers/vc4/vc4_fence.c
> index b6fb2a8..f61e7c6 100644
> --- a/src/gallium/drivers/vc4/vc4_fence.c
> +++ b/src/gallium/drivers/vc4/vc4_fence.c
> @@ -54,20 +54,21 @@ vc4_fence_reference(struct pipe_screen *pscreen,
>          struct vc4_fence *old = *p;
>
>          if (pipe_reference(&(*p)->reference, &f->reference)) {
>                  free(old);
>          }
>          *p = f;
>  }
>
>  static boolean
>  vc4_fence_finish(struct pipe_screen *pscreen,
> +		 struct pipe_context *ctx,
>                   struct pipe_fence_handle *pf,
>                   uint64_t timeout_ns)
>  {
>          struct vc4_screen *screen = vc4_screen(pscreen);
>          struct vc4_fence *f = (struct vc4_fence *)pf;
>
>          return vc4_wait_seqno(screen, f->seqno, timeout_ns, "fence wait");
>  }
>
>  struct vc4_fence *
> diff --git a/src/gallium/drivers/virgl/virgl_screen.c b/src/gallium/drivers/virgl/virgl_screen.c
> index fd3d35d..e01b5b4 100644
> --- a/src/gallium/drivers/virgl/virgl_screen.c
> +++ b/src/gallium/drivers/virgl/virgl_screen.c
> @@ -517,20 +517,21 @@ static void virgl_fence_reference(struct pipe_screen *screen,
>                                    struct pipe_fence_handle **ptr,
>                                    struct pipe_fence_handle *fence)
>  {
>     struct virgl_screen *vscreen = virgl_screen(screen);
>     struct virgl_winsys *vws = vscreen->vws;
>
>     vws->fence_reference(vws, ptr, fence);
>  }
>
>  static boolean virgl_fence_finish(struct pipe_screen *screen,
> +                                  struct pipe_context *ctx,
>                                    struct pipe_fence_handle *fence,
>                                    uint64_t timeout)
>  {
>     struct virgl_screen *vscreen = virgl_screen(screen);
>     struct virgl_winsys *vws = vscreen->vws;
>
>     return vws->fence_wait(vws, fence, timeout);
>  }
>
>  static uint64_t
> diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h
> index 755291a..dd40e07 100644
> --- a/src/gallium/include/pipe/p_screen.h
> +++ b/src/gallium/include/pipe/p_screen.h
> @@ -235,25 +235,34 @@ struct pipe_screen {
>                                void *winsys_drawable_handle,
>                                struct pipe_box *subbox );
>
>     /** Set ptr = fence, with reference counting */
>     void (*fence_reference)( struct pipe_screen *screen,
>                              struct pipe_fence_handle **ptr,
>                              struct pipe_fence_handle *fence );
>
>     /**
>      * Wait for the fence to finish.
> +    *
> +    * If the fence was created with PIPE_FLUSH_DEFERRED, and the context is
> +    * still unflushed, and the ctx parameter of fence_finish is equal to
> +    * the context where the fence was created, fence_finish will flush
> +    * the context prior to waiting for the fence.
> +    *
> +    * In all other cases, the ctx parameter has no effect.
> +    *
>      * \param timeout  in nanoseconds (may be PIPE_TIMEOUT_INFINITE).
>      */
> -   boolean (*fence_finish)( struct pipe_screen *screen,
> -                            struct pipe_fence_handle *fence,
> -                            uint64_t timeout );
> +   boolean (*fence_finish)(struct pipe_screen *screen,
> +                           struct pipe_context *ctx,
> +                           struct pipe_fence_handle *fence,
> +                           uint64_t timeout);
>
>     /**
>      * Returns a driver-specific query.
>      *
>      * If \p info is NULL, the number of available queries is returned.
>      * Otherwise, the driver query at the specified \p index is returned
>      * in \p info. The function returns non-zero on success.
>      */
>     int (*get_driver_query_info)(struct pipe_screen *screen,
>                                  unsigned index,
> diff --git a/src/gallium/state_trackers/clover/core/event.cpp b/src/gallium/state_trackers/clover/core/event.cpp
> index d75b839..8275e16 100644
> --- a/src/gallium/state_trackers/clover/core/event.cpp
> +++ b/src/gallium/state_trackers/clover/core/event.cpp
> @@ -134,21 +134,21 @@ hard_event::~hard_event() {
>  cl_int
>  hard_event::status() const {
>     pipe_screen *screen = queue()->device().pipe;
>
>     if (event::status() < 0)
>        return event::status();
>
>     else if (!_fence)
>        return CL_QUEUED;
>
> -   else if (!screen->fence_finish(screen, _fence, 0))
> +   else if (!screen->fence_finish(screen, NULL, _fence, 0))
>        return CL_SUBMITTED;
>
>     else
>        return CL_COMPLETE;
>  }
>
>  command_queue *
>  hard_event::queue() const {
>     return &_queue();
>  }
> @@ -161,21 +161,21 @@ hard_event::command() const {
>  void
>  hard_event::wait() const {
>     pipe_screen *screen = queue()->device().pipe;
>
>     event::wait();
>
>     if (status() == CL_QUEUED)
>        queue()->flush();
>
>     if (!_fence ||
> -       !screen->fence_finish(screen, _fence, PIPE_TIMEOUT_INFINITE))
> +       !screen->fence_finish(screen, NULL, _fence, PIPE_TIMEOUT_INFINITE))
>        throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST);
>  }
>
>  const lazy<cl_ulong> &
>  hard_event::time_queued() const {
>     return _time_queued;
>  }
>
>  const lazy<cl_ulong> &
>  hard_event::time_submit() const {
> diff --git a/src/gallium/state_trackers/dri/dri2.c b/src/gallium/state_trackers/dri/dri2.c
> index c22a8cd..9803b0e 100644
> --- a/src/gallium/state_trackers/dri/dri2.c
> +++ b/src/gallium/state_trackers/dri/dri2.c
> @@ -1245,21 +1245,21 @@ dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
>
>     pipe->blit(pipe, &blit);
>
>     if (flush_flag == __BLIT_FLAG_FLUSH) {
>        pipe->flush_resource(pipe, dst->texture);
>        ctx->st->flush(ctx->st, 0, NULL);
>     } else if (flush_flag == __BLIT_FLAG_FINISH) {
>        screen = dri_screen(ctx->sPriv)->base.screen;
>        pipe->flush_resource(pipe, dst->texture);
>        ctx->st->flush(ctx->st, 0, &fence);
> -      (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
> +      (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);
>        screen->fence_reference(screen, &fence, NULL);
>     }
>  }
>
>  static void *
>  dri2_map_image(__DRIcontext *context, __DRIimage *image,
>                  int x0, int y0, int width, int height,
>                  unsigned int flags, int *stride, void **data)
>  {
>     struct dri_context *ctx = dri_context(context);
> @@ -1444,27 +1444,27 @@ static GLboolean
>  dri2_client_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags,
>                        uint64_t timeout)
>  {
>     struct dri2_fence *fence = (struct dri2_fence*)_fence;
>     struct dri_screen *driscreen = fence->driscreen;
>     struct pipe_screen *screen = driscreen->base.screen;
>
>     /* No need to flush. The context was flushed when the fence was created. */
>
>     if (fence->pipe_fence)
> -      return screen->fence_finish(screen, fence->pipe_fence, timeout);
> +      return screen->fence_finish(screen, NULL, fence->pipe_fence, timeout);
>     else if (fence->cl_event) {
>        struct pipe_fence_handle *pipe_fence =
>           driscreen->opencl_dri_event_get_fence(fence->cl_event);
>
>        if (pipe_fence)
> -         return screen->fence_finish(screen, pipe_fence, timeout);
> +         return screen->fence_finish(screen, NULL, pipe_fence, timeout);
>        else
>           return driscreen->opencl_dri_event_wait(fence->cl_event, timeout);
>     }
>     else {
>        assert(0);
>        return false;
>     }
>  }
>
>  static void
> diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c
> index adc5128..edcd0e6 100644
> --- a/src/gallium/state_trackers/dri/dri_drawable.c
> +++ b/src/gallium/state_trackers/dri/dri_drawable.c
> @@ -518,21 +518,21 @@ dri_flush(__DRIcontext *cPriv,
>         *
>         * Then flushes to insert a fence at the current rendering position, and
>         * pushes that fence on the queue. This requires that the st_context_iface
>         * flush method returns a fence even if there are no commands to flush.
>         */
>        struct pipe_screen *screen = drawable->screen->base.screen;
>        struct pipe_fence_handle *fence;
>
>        fence = swap_fences_pop_front(drawable);
>        if (fence) {
> -         (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
> +         (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);
>           screen->fence_reference(screen, &fence, NULL);
>        }
>
>        ctx->st->flush(ctx->st, flush_flags, &fence);
>
>        if (fence) {
>           swap_fences_push_back(drawable, fence);
>           screen->fence_reference(screen, &fence, NULL);
>        }
>     }
> diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c
> index 5799cce..8d1b360 100644
> --- a/src/gallium/state_trackers/glx/xlib/xm_api.c
> +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c
> @@ -1369,21 +1369,21 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
>
>
>  void XMesaFlush( XMesaContext c )
>  {
>     if (c && c->xm_visual->display) {
>        XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display);
>        struct pipe_fence_handle *fence = NULL;
>
>        c->st->flush(c->st, ST_FLUSH_FRONT, &fence);
>        if (fence) {
> -         xmdpy->screen->fence_finish(xmdpy->screen, fence,
> +         xmdpy->screen->fence_finish(xmdpy->screen, NULL, fence,
>                                       PIPE_TIMEOUT_INFINITE);
>           xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL);
>        }
>        XFlush( c->xm_visual->display );
>     }
>  }
>
>
>
>
> diff --git a/src/gallium/state_trackers/nine/swapchain9.c b/src/gallium/state_trackers/nine/swapchain9.c
> index bc01c2d..08ee482 100644
> --- a/src/gallium/state_trackers/nine/swapchain9.c
> +++ b/src/gallium/state_trackers/nine/swapchain9.c
> @@ -614,21 +614,21 @@ struct end_present_struct {
>      struct pipe_fence_handle *fence_to_wait;
>      ID3DPresent *present;
>      D3DWindowBuffer *present_handle;
>      HWND hDestWindowOverride;
>  };
>
>  static void work_present(void *data)
>  {
>      struct end_present_struct *work = data;
>      if (work->fence_to_wait) {
> -        (void) work->screen->fence_finish(work->screen, work->fence_to_wait, PIPE_TIMEOUT_INFINITE);
> +        (void) work->screen->fence_finish(work->screen, NULL, work->fence_to_wait, PIPE_TIMEOUT_INFINITE);
>          work->screen->fence_reference(work->screen, &(work->fence_to_wait), NULL);
>      }
>      ID3DPresent_PresentBuffer(work->present, work->present_handle, work->hDestWindowOverride, NULL, NULL, NULL, 0);
>      free(work);
>  }
>
>  static void pend_present(struct NineSwapChain9 *This,
>                           HWND hDestWindowOverride)
>  {
>      struct end_present_struct *work = calloc(1, sizeof(struct end_present_struct));
> @@ -736,32 +736,32 @@ present( struct NineSwapChain9 *This,
>      }
>
>      This->rendering_done = TRUE;
>  bypass_rendering:
>
>      if (dwFlags & D3DPRESENT_DONOTWAIT) {
>          UNTESTED(2);
>          BOOL still_draw = FALSE;
>          fence = swap_fences_see_front(This);
>          if (fence) {
> -            still_draw = !This->screen->fence_finish(This->screen, fence, 0);
> +            still_draw = !This->screen->fence_finish(This->screen, NULL, fence, 0);
>              This->screen->fence_reference(This->screen, &fence, NULL);
>          }
>          if (still_draw)
>              return D3DERR_WASSTILLDRAWING;
>      }
>
>      if (!This->enable_threadpool) {
>          This->tasks[0]=NULL;
>          fence = swap_fences_pop_front(This);
>          if (fence) {
> -            (void) This->screen->fence_finish(This->screen, fence, PIPE_TIMEOUT_INFINITE);
> +            (void) This->screen->fence_finish(This->screen, NULL, fence, PIPE_TIMEOUT_INFINITE);
>              This->screen->fence_reference(This->screen, &fence, NULL);
>          }
>
>          hr = ID3DPresent_PresentBuffer(This->present, This->present_handles[0], hDestWindowOverride, pSourceRect, pDestRect, pDirtyRegion, dwFlags);
>
>          if (FAILED(hr)) { UNTESTED(3);return hr; }
>      } else {
>          pend_present(This, hDestWindowOverride);
>      }
>      This->rendering_done = FALSE;
> diff --git a/src/gallium/state_trackers/vdpau/presentation.c b/src/gallium/state_trackers/vdpau/presentation.c
> index e7f387e..2862eaf 100644
> --- a/src/gallium/state_trackers/vdpau/presentation.c
> +++ b/src/gallium/state_trackers/vdpau/presentation.c
> @@ -320,21 +320,21 @@ vlVdpPresentationQueueBlockUntilSurfaceIdle(VdpPresentationQueue presentation_qu
>     if (!pq)
>        return VDP_STATUS_INVALID_HANDLE;
>
>     surf = vlGetDataHTAB(surface);
>     if (!surf)
>        return VDP_STATUS_INVALID_HANDLE;
>
>     pipe_mutex_lock(pq->device->mutex);
>     if (surf->fence) {
>        screen = pq->device->vscreen->pscreen;
> -      screen->fence_finish(screen, surf->fence, PIPE_TIMEOUT_INFINITE);
> +      screen->fence_finish(screen, NULL, surf->fence, PIPE_TIMEOUT_INFINITE);
>        screen->fence_reference(screen, &surf->fence, NULL);
>     }
>     pipe_mutex_unlock(pq->device->mutex);
>
>     return vlVdpPresentationQueueGetTime(presentation_queue, first_presentation_time);
>  }
>
>  /**
>   * Poll the current queue status of a surface.
>   */
> @@ -362,21 +362,21 @@ vlVdpPresentationQueueQuerySurfaceStatus(VdpPresentationQueue presentation_queue
>     *first_presentation_time = 0;
>
>     if (!surf->fence) {
>        if (pq->last_surf == surf)
>           *status = VDP_PRESENTATION_QUEUE_STATUS_VISIBLE;
>        else
>           *status = VDP_PRESENTATION_QUEUE_STATUS_IDLE;
>     } else {
>        pipe_mutex_lock(pq->device->mutex);
>        screen = pq->device->vscreen->pscreen;
> -      if (screen->fence_finish(screen, surf->fence, 0)) {
> +      if (screen->fence_finish(screen, NULL, surf->fence, 0)) {
>           screen->fence_reference(screen, &surf->fence, NULL);
>           *status = VDP_PRESENTATION_QUEUE_STATUS_VISIBLE;
>           pipe_mutex_unlock(pq->device->mutex);
>
>           // We actually need to query the timestamp of the last VSYNC event from the hardware
>           vlVdpPresentationQueueGetTime(presentation_queue, first_presentation_time);
>           *first_presentation_time += 1;
>        } else {
>           *status = VDP_PRESENTATION_QUEUE_STATUS_QUEUED;
>           pipe_mutex_unlock(pq->device->mutex);
> diff --git a/src/gallium/state_trackers/xa/xa_context.c b/src/gallium/state_trackers/xa/xa_context.c
> index 5553beb..715b48d 100644
> --- a/src/gallium/state_trackers/xa/xa_context.c
> +++ b/src/gallium/state_trackers/xa/xa_context.c
> @@ -376,21 +376,21 @@ xa_fence_get(struct xa_context *ctx)
>  XA_EXPORT int
>  xa_fence_wait(struct xa_fence *fence, uint64_t timeout)
>  {
>      if (!fence)
>  	return XA_ERR_NONE;
>
>      if (fence->pipe_fence) {
>  	struct pipe_screen *screen = fence->xa->screen;
>  	boolean timed_out;
>
> -	timed_out = !screen->fence_finish(screen, fence->pipe_fence, timeout);
> +	timed_out = !screen->fence_finish(screen, NULL, fence->pipe_fence, timeout);
>  	if (timed_out)
>  	    return -XA_ERR_BUSY;
>
>  	screen->fence_reference(screen, &fence->pipe_fence, NULL);
>      }
>      return XA_ERR_NONE;
>  }
>
>  XA_EXPORT void
>  xa_fence_destroy(struct xa_fence *fence)
> diff --git a/src/gallium/state_trackers/xvmc/surface.c b/src/gallium/state_trackers/xvmc/surface.c
> index 199712b..a4cd2aa 100644
> --- a/src/gallium/state_trackers/xvmc/surface.c
> +++ b/src/gallium/state_trackers/xvmc/surface.c
> @@ -481,21 +481,21 @@ Status XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status)
>
>     assert(status);
>
>     surface_priv = surface->privData;
>     context_priv = surface_priv->context->privData;
>     pipe = context_priv->pipe;
>
>     *status = 0;
>
>     if (surface_priv->fence)
> -      if (!pipe->screen->fence_finish(pipe->screen, surface_priv->fence, 0))
> +      if (!pipe->screen->fence_finish(pipe->screen, NULL, surface_priv->fence, 0))
>           *status |= XVMC_RENDERING;
>
>     return Success;
>  }
>
>  PUBLIC
>  Status XvMCDestroySurface(Display *dpy, XvMCSurface *surface)
>  {
>     XvMCSurfacePrivate *surface_priv;
>     XvMCContextPrivate *context_priv;
> diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c
> index 82affd2..5cab5a7 100644
> --- a/src/mesa/state_tracker/st_cb_flush.c
> +++ b/src/mesa/state_tracker/st_cb_flush.c
> @@ -91,21 +91,21 @@ void st_flush(struct st_context *st,
>  /**
>   * Flush, and wait for completion.
>   */
>  void st_finish( struct st_context *st )
>  {
>     struct pipe_fence_handle *fence = NULL;
>
>     st_flush(st, &fence, 0);
>
>     if(fence) {
> -      st->pipe->screen->fence_finish(st->pipe->screen, fence,
> +      st->pipe->screen->fence_finish(st->pipe->screen, NULL, fence,
>                                       PIPE_TIMEOUT_INFINITE);
>        st->pipe->screen->fence_reference(st->pipe->screen, &fence, NULL);
>     }
>  }
>
>
>
>  /**
>   * Called via ctx->Driver.Flush()
>   */
> diff --git a/src/mesa/state_tracker/st_cb_syncobj.c b/src/mesa/state_tracker/st_cb_syncobj.c
> index 69f2a28..1fa1403 100644
> --- a/src/mesa/state_tracker/st_cb_syncobj.c
> +++ b/src/mesa/state_tracker/st_cb_syncobj.c
> @@ -80,21 +80,21 @@ static void st_check_sync(struct gl_context *ctx, struct gl_sync_object *obj)
>  {
>     struct pipe_screen *screen = st_context(ctx)->pipe->screen;
>     struct st_sync_object *so = (struct st_sync_object*)obj;
>
>     /* If the fence doesn't exist, assume it's signalled. */
>     if (!so->fence) {
>        so->b.StatusFlag = GL_TRUE;
>        return;
>     }
>
> -   if (screen->fence_finish(screen, so->fence, 0)) {
> +   if (screen->fence_finish(screen, NULL, so->fence, 0)) {
>        screen->fence_reference(screen, &so->fence, NULL);
>        so->b.StatusFlag = GL_TRUE;
>     }
>  }
>
>  static void st_client_wait_sync(struct gl_context *ctx,
>                                  struct gl_sync_object *obj,
>                                  GLbitfield flags, GLuint64 timeout)
>  {
>     struct pipe_screen *screen = st_context(ctx)->pipe->screen;
> @@ -103,21 +103,21 @@ static void st_client_wait_sync(struct gl_context *ctx,
>     /* If the fence doesn't exist, assume it's signalled. */
>     if (!so->fence) {
>        so->b.StatusFlag = GL_TRUE;
>        return;
>     }
>
>     /* We don't care about GL_SYNC_FLUSH_COMMANDS_BIT, because flush is
>      * already called when creating a fence. */
>
>     if (so->fence &&
> -       screen->fence_finish(screen, so->fence, timeout)) {
> +       screen->fence_finish(screen, NULL, so->fence, timeout)) {
>        screen->fence_reference(screen, &so->fence, NULL);
>        so->b.StatusFlag = GL_TRUE;
>     }
>  }
>
>  static void st_server_wait_sync(struct gl_context *ctx,
>                                  struct gl_sync_object *obj,
>                                  GLbitfield flags, GLuint64 timeout)
>  {
>     /* NO-OP.
>


More information about the mesa-dev mailing list