[Intel-gfx] [PATCH] manage pixmaps with EXA

Jesse Barnes jbarnes at virtuousgeek.org
Thu Apr 9 22:51:51 CEST 2009


On Thu, 9 Apr 2009 10:45:14 -0700
Jesse Barnes <jbarnes at virtuousgeek.org> wrote:

> On Thu, 09 Apr 2009 10:04:37 -0700
> Eric Anholt <eric at anholt.net> wrote:
> 
> > On Wed, 2009-04-08 at 16:56 -0700, Jesse Barnes wrote:
> > > I started looking at #20739 and it appears to be a server bug in
> > > the EXA migration code somewhere.  Rather than digging through
> > > that when we're likely to remove EXA support soon, I just added
> > > support for driver managed pixmaps, which fixes also fixes the
> > > bug.
> > > 
> > > This is a fairly significant change so close to release, but I
> > > thought I'd post it for comments.
> > > 
> > > The patch isn't actually as big as it appears; it mainly moves the
> > > UXA pixmap create/destroy routines up above the EXA init call so
> > > they can be used for both cases.
> > 
> > NAK -
> > 
> > If you have kernel memory management, you should be using UXA.
> > Non-kernel memory management is the only reason we have EXA around
> > at all, since we get stuck with non-kernel memory management on the
> > second server pre-KMS.  This patch would remove that support, so we
> > might as well just remove EXA entirely in that case.
> 
> As we discussed the alternative would be to beef up the fake bufmgr to
> handle that case better.  Aside from providing GTT maps in the fake
> bufmgr what else do you think needs to be done?

Here's a version that works a bit better.  We were getting rendering
requests with this patch after VT switch.  After VT switch the batch
code gets torn down, so we were hitting asserts in the dword emit
code.  Sprinkling a few vtSema checks around made things stable for the
two X server VT switch case (one with GEM, one with fake bufmgr).

-- 
Jesse Barnes, Intel Open Source Technology Center

diff --git a/src/i830.h b/src/i830.h
index f933917..43e69cc 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -86,7 +86,6 @@ unsigned long long I830TexOffsetStart(PixmapPtr pPix);
 #include "uxa.h"
 Bool i830_uxa_init(ScreenPtr pScreen);
 void i830_uxa_create_screen_resources(ScreenPtr pScreen);
-void i830_uxa_block_handler (ScreenPtr pScreen);
 Bool i830_get_aperture_space(ScrnInfoPtr pScrn, drm_intel_bo **bo_table,
 			     int num_bos);
 #endif
@@ -94,6 +93,7 @@ Bool i830_get_aperture_space(ScrnInfoPtr pScrn, drm_intel_bo **bo_table,
 #if defined(I830_USE_UXA) || defined(I830_USE_EXA)
 dri_bo *i830_get_pixmap_bo (PixmapPtr pixmap);
 void i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo *bo);
+void i830_block_handler (ScreenPtr pScreen);
 #endif
 
 #ifdef I830_USE_XAA
@@ -520,8 +520,8 @@ typedef struct _I830Rec {
 #endif
 #ifdef I830_USE_UXA
    uxa_driver_t *uxa_driver;
-   Bool need_flush;
 #endif
+   Bool need_flush;
    Bool need_sync;
 #if defined(I830_USE_EXA) || defined(I830_USE_UXA)
    PixmapPtr pSrcPixmap;
diff --git a/src/i830_accel.c b/src/i830_accel.c
index 9f5bcb5..b1f296c 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -67,28 +67,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 unsigned long
 intel_get_pixmap_offset(PixmapPtr pPix)
 {
-#if defined(I830_USE_EXA) || defined(I830_USE_UXA)
     ScreenPtr pScreen = pPix->drawable.pScreen;
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (pI830->accel == ACCEL_EXA)
-	return exaGetPixmapOffset(pPix);
-#endif
     return (unsigned long)pPix->devPrivate.ptr - (unsigned long)pI830->FbBase;
 }
 
 unsigned long
 intel_get_pixmap_pitch(PixmapPtr pPix)
 {
-#ifdef I830_USE_EXA
-    ScreenPtr pScreen = pPix->drawable.pScreen;
-    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
-
-    if (pI830->accel == ACCEL_EXA)
-	return exaGetPixmapPitch(pPix);
-#endif
     return (unsigned long)pPix->devKind;
 }
 
@@ -177,7 +165,7 @@ I830Sync(ScrnInfoPtr pScrn)
    if (I810_DEBUG & (DEBUG_VERBOSE_ACCEL | DEBUG_VERBOSE_SYNC))
       ErrorF("I830Sync\n");
 
-   if (pI830->accel == ACCEL_NONE)
+   if (pI830->accel == ACCEL_NONE || !pScrn->vtSema)
        return;
 
 #ifdef XF86DRI
diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
index ff5f0c2..1c8fbdb 100644
--- a/src/i830_batchbuffer.c
+++ b/src/i830_batchbuffer.c
@@ -98,7 +98,8 @@ intel_nondrm_wait(unsigned int fence, void *priv)
 {
     ScrnInfoPtr pScrn = priv;
 
-    i830_wait_ring_idle(pScrn);
+    if (pScrn->vtSema)
+	i830_wait_ring_idle(pScrn);
 }
 
 static void
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 32ca6c9..89af2b1 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2660,8 +2660,8 @@ I830BlockHandler(int i,
     }
 
 #ifdef I830_USE_UXA
-    if (pI830->accel == ACCEL_UXA)
-	i830_uxa_block_handler (pScreen);
+    if (pI830->accel == ACCEL_UXA || pI830->accel == ACCEL_EXA)
+	i830_block_handler (pScreen);
 #endif
 
     I830VideoBlockHandler(i, blockData, pTimeout, pReadmask);
@@ -3884,6 +3884,7 @@ void
 i830WaitSync(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
+   ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
 
    switch (pI830->accel) {
 #ifdef I830_USE_XAA
@@ -3896,20 +3897,17 @@ i830WaitSync(ScrnInfoPtr pScrn)
 #endif
 #ifdef I830_USE_EXA
    case ACCEL_EXA:
-      if (pI830->EXADriverPtr) {
-	 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
-	 exaWaitSync(pScreen);
-      }
-      break;
+       exaWaitSync(pScreen);
+       /* fall through */
 #endif
 #ifdef I830_USE_UXA
    case ACCEL_UXA:
-      if (pI830->uxa_driver && pI830->need_sync) {
+#endif
+      if (pI830->need_sync) {
 	 pI830->need_sync = FALSE;
 	 I830Sync(pScrn);
       }
       break;
-#endif
    default:
       break;
    }
@@ -3931,8 +3929,9 @@ i830MarkSync(ScrnInfoPtr pScrn)
    case ACCEL_EXA:
       if (pI830->EXADriverPtr) {
 	 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+	 pI830->need_sync = TRUE;
 	 exaMarkSync(pScreen);
-      }
+     }
       break;
 #endif
 #ifdef I830_USE_UXA
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 39011bc..ae79723 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -517,8 +517,6 @@ i830_transform_is_affine (PictTransformPtr t)
     return t->matrix[2][0] == 0 && t->matrix[2][1] == 0;
 }
 
-#ifdef XF86DRM_MODE
-
 static void *
 I830EXACreatePixmap(ScreenPtr screen, int size, int align)
 {
@@ -563,63 +561,98 @@ static Bool I830EXAPixmapIsOffscreen(PixmapPtr pPix)
     return FALSE;
 }
 
-static Bool I830EXAPrepareAccess(PixmapPtr pPix, int index)
+static Bool
+i830_prepare_access (PixmapPtr pixmap, uxa_access_t access)
 {
-    ScreenPtr screen = pPix->drawable.pScreen;
-    ScrnInfoPtr scrn = xf86Screens[screen->myNum];
-    I830Ptr i830 = I830PTR(scrn);
-    struct i830_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix);
+    dri_bo *bo = i830_get_pixmap_bo (pixmap);
 
-    if (!driver_priv) {
-	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: no driver private?\n",
-		   __FUNCTION__);
-	return FALSE;
-    }
+    if (bo) {
+	ScreenPtr screen = pixmap->drawable.pScreen;
+	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+	I830Ptr i830 = I830PTR(scrn);
+	
+	intel_batch_flush(scrn, FALSE);
+	/* XXX: dri_bo_map should handle syncing for us, what's the deal? */
+	if (i830->need_sync) {
+	    I830Sync(scrn);
+	    i830->need_sync = FALSE;
+	}
 
-    if (!driver_priv->bo) {
-	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: no buffer object?\n",
-		   __FUNCTION__);
-	return TRUE;
-    }
+	/* No VT sema or GEM?  No GTT mapping. */
+	if (!scrn->vtSema || !i830->memory_manager) {
+	    if (dri_bo_map(bo, access == UXA_ACCESS_RW) != 0)
+		return FALSE;
+	    pixmap->devPrivate.ptr = bo->virtual;
+	    return TRUE;
+	}
 
-    intel_batch_flush(scrn, FALSE);
-    if (i830->need_sync) {
-	I830Sync(scrn);
-	i830->need_sync = FALSE;
+	/* Kernel manages fences at GTT map/fault time */
+	if (i830->kernel_exec_fencing) {
+	    if (drm_intel_gem_bo_map_gtt(bo)) {
+		xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: bo map failed\n",
+			   __FUNCTION__);
+		return FALSE;
+	    }
+	    pixmap->devPrivate.ptr = bo->virtual;
+	} else { /* or not... */
+	    if (drm_intel_bo_pin(bo, 4096) != 0)
+		return FALSE;
+	    drm_intel_gem_bo_start_gtt_access(bo, access == UXA_ACCESS_RW);
+	    pixmap->devPrivate.ptr = i830->FbBase + bo->offset;
+	}
     }
-    if (drm_intel_gem_bo_map_gtt(driver_priv->bo)) {
-	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: bo map failed\n",
-		   __FUNCTION__);
-	return FALSE;
+    return TRUE;
+}
+
+static Bool
+i830_exa_prepare_access(PixmapPtr pixmap, int index)
+{
+    return i830_prepare_access(pixmap, UXA_ACCESS_RW);
+}
+
+static void
+i830_finish_access (PixmapPtr pixmap)
+{
+    dri_bo *bo = i830_get_pixmap_bo (pixmap);
+
+    if (bo) {
+	ScreenPtr screen = pixmap->drawable.pScreen;
+	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+	I830Ptr i830 = I830PTR(scrn);
+
+	if (bo == i830->front_buffer->bo)
+	    i830->need_flush = TRUE;
+
+	if (!scrn->vtSema || !i830->memory_manager) {
+	    dri_bo_unmap(bo);
+	    pixmap->devPrivate.ptr = NULL;
+	    return;
+	}
+
+	if (i830->kernel_exec_fencing)
+	    drm_intel_gem_bo_unmap_gtt(bo);
+	else
+	    drm_intel_bo_unpin(bo);
+	pixmap->devPrivate.ptr = NULL;
     }
-    pPix->devPrivate.ptr = driver_priv->bo->virtual;
+}
 
-    return TRUE;
+static void
+i830_exa_finish_access (PixmapPtr pixmap, int index)
+{
+    i830_finish_access(pixmap);
 }
 
-static void I830EXAFinishAccess(PixmapPtr pPix, int index)
+void
+i830_block_handler (ScreenPtr screen)
 {
-    ScreenPtr screen = pPix->drawable.pScreen;
     ScrnInfoPtr scrn = xf86Screens[screen->myNum];
     I830Ptr i830 = I830PTR(scrn);
-    struct i830_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix);
-
-    if (!driver_priv) {
-	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: no driver private?\n",
-		   __FUNCTION__);
-	return;
-    }
 
-    if (!driver_priv->bo) {
-	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: no buffer object?\n",
-		   __FUNCTION__);
-	return;
+    if (i830->need_flush) {
+	dri_bo_wait_rendering (i830->front_buffer->bo);
+	i830->need_flush = FALSE;
     }
-
-    dri_bo_unmap(driver_priv->bo);
-    pPix->devPrivate.ptr = NULL;
-    if (driver_priv->bo == i830->front_buffer->bo)
-	i830->need_flush = TRUE;
 }
 
 static Bool I830EXAModifyPixmapHeader(PixmapPtr pPix, int width, int height,
@@ -634,15 +667,6 @@ static Bool I830EXAModifyPixmapHeader(PixmapPtr pPix, int width, int height,
     if (!driver_priv)
 	return FALSE;
 
-    if (pI830->use_drm_mode &&
-	drmmode_is_rotate_pixmap(pScrn, pPixData, &driver_priv->bo)) {
-	/* this is a rotate pixmap */
-	dri_bo_unmap(driver_priv->bo);
-	dri_bo_reference(driver_priv->bo);
-        miModifyPixmapHeader(pPix, width, height, depth,
-			     bitsPerPixel, devKind, NULL);
-    }
-
     if (pPixData == pI830->FbBase + pScrn->fbOffset) {
 	if (driver_priv->bo)
 		dri_bo_unreference(driver_priv->bo);
@@ -660,8 +684,6 @@ static Bool I830EXAModifyPixmapHeader(PixmapPtr pPix, int width, int height,
     return FALSE;
 }
 
-#endif /* XF86DRM_MODE */
-
 Bool
 I830EXAInit(ScreenPtr pScreen)
 {
@@ -688,37 +710,19 @@ I830EXAInit(ScreenPtr pScreen)
 	       "EXA compatibility mode.  Output rotation rendering "
 	       "performance may suffer\n");
 #endif
-    if (!pI830->use_drm_mode) {
-	pI830->EXADriverPtr->memoryBase = pI830->FbBase;
-	if (pI830->exa_offscreen) {
-	    pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
-	    pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
-		pI830->exa_offscreen->size;
-	} else {
-	    pI830->EXADriverPtr->offScreenBase = pI830->FbMapSize;
-	    pI830->EXADriverPtr->memorySize = pI830->FbMapSize;
-	}
-	pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
-    } else {
-#ifdef XF86DRM_MODE
-	pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
-	pI830->EXADriverPtr->PrepareAccess = I830EXAPrepareAccess;
-	pI830->EXADriverPtr->FinishAccess = I830EXAFinishAccess;
+
+    pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
+    pI830->EXADriverPtr->PrepareAccess = i830_exa_prepare_access;
+    pI830->EXADriverPtr->FinishAccess = i830_exa_finish_access;
+#if EXA_VERSION_MINOR >= 2
+    pI830->EXADriverPtr->PixmapIsOffscreen = i830_exa_pixmap_is_offscreen;
+#endif
 #if EXA_VERSION_MINOR >= 4
-	pI830->EXADriverPtr->CreatePixmap = I830EXACreatePixmap;
-	pI830->EXADriverPtr->DestroyPixmap = I830EXADestroyPixmap;
-	pI830->EXADriverPtr->PixmapIsOffscreen = I830EXAPixmapIsOffscreen;
-	pI830->EXADriverPtr->ModifyPixmapHeader = I830EXAModifyPixmapHeader;
+    pI830->EXADriverPtr->CreatePixmap = I830EXACreatePixmap;
+    pI830->EXADriverPtr->DestroyPixmap = I830EXADestroyPixmap;
+    pI830->EXADriverPtr->PixmapIsOffscreen = I830EXAPixmapIsOffscreen;
+    pI830->EXADriverPtr->ModifyPixmapHeader = I830EXAModifyPixmapHeader;
 #endif
-#endif /* XF86DRM_MODE */
-    }
-
-    DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, "
-	    "memorySize 0x%x\n",
-	    pI830->EXADriverPtr->memoryBase,
-	    pI830->EXADriverPtr->memoryBase + pI830->EXADriverPtr->memorySize,
-	    pI830->EXADriverPtr->offScreenBase,
-	    pI830->EXADriverPtr->memorySize);
 
     pI830->EXADriverPtr->pixmapOffsetAlign = pI830->accel_pixmap_offset_alignment;
     pI830->EXADriverPtr->pixmapPitchAlign = pI830->accel_pixmap_pitch_alignment;
@@ -757,10 +761,6 @@ I830EXAInit(ScreenPtr pScreen)
  	pI830->EXADriverPtr->Composite = i965_composite;
  	pI830->EXADriverPtr->DoneComposite = i830_done_composite;
     }
-#if EXA_VERSION_MINOR >= 2
-    if (!pI830->use_drm_mode)
-	pI830->EXADriverPtr->PixmapIsOffscreen = i830_exa_pixmap_is_offscreen;
-#endif
 
     if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
@@ -816,7 +816,7 @@ i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo *bo)
 	dixSetPrivate(&pixmap->devPrivates, &uxa_pixmap_index, bo);
     }
 #endif
-#ifdef XF86DRM_MODE
+
     if (i830->accel == ACCEL_EXA) {
 	struct i830_exa_pixmap_priv *driver_priv =
 	    exaGetPixmapDriverPrivate(pixmap);
@@ -825,7 +825,7 @@ i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo *bo)
 	    driver_priv->bo = bo;
 	}
     }
-#endif
+
 }
 #if defined(I830_USE_UXA)
 
@@ -836,88 +836,6 @@ i830_uxa_set_pixmap_bo (PixmapPtr pixmap, dri_bo *bo)
 }
 
 static Bool
-i830_uxa_prepare_access (PixmapPtr pixmap, uxa_access_t access)
-{
-    dri_bo *bo = i830_get_pixmap_bo (pixmap);
-
-    if (bo) {
-	ScreenPtr screen = pixmap->drawable.pScreen;
-	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
-	I830Ptr i830 = I830PTR(scrn);
-	
-	intel_batch_flush(scrn, FALSE);
-	/* XXX: dri_bo_map should handle syncing for us, what's the deal? */
-	if (i830->need_sync) {
-	    I830Sync(scrn);
-	    i830->need_sync = FALSE;
-	}
-
-	/* No VT sema or GEM?  No GTT mapping. */
-	if (!scrn->vtSema || !i830->memory_manager) {
-	    if (dri_bo_map(bo, access == UXA_ACCESS_RW) != 0)
-		return FALSE;
-	    pixmap->devPrivate.ptr = bo->virtual;
-	    return TRUE;
-	}
-
-	/* Kernel manages fences at GTT map/fault time */
-	if (i830->kernel_exec_fencing) {
-	    if (drm_intel_gem_bo_map_gtt(bo)) {
-		xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: bo map failed\n",
-			   __FUNCTION__);
-		return FALSE;
-	    }
-	    pixmap->devPrivate.ptr = bo->virtual;
-	} else { /* or not... */
-	    if (drm_intel_bo_pin(bo, 4096) != 0)
-		return FALSE;
-	    drm_intel_gem_bo_start_gtt_access(bo, access == UXA_ACCESS_RW);
-	    pixmap->devPrivate.ptr = i830->FbBase + bo->offset;
-	}
-    }
-    return TRUE;
-}
-
-static void
-i830_uxa_finish_access (PixmapPtr pixmap)
-{
-    dri_bo *bo = i830_get_pixmap_bo (pixmap);
-
-    if (bo) {
-	ScreenPtr screen = pixmap->drawable.pScreen;
-	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
-	I830Ptr i830 = I830PTR(scrn);
-
-	if (bo == i830->front_buffer->bo)
-	    i830->need_flush = TRUE;
-
-	if (!scrn->vtSema || !i830->memory_manager) {
-	    dri_bo_unmap(bo);
-	    pixmap->devPrivate.ptr = NULL;
-	    return;
-	}
-
-	if (i830->kernel_exec_fencing)
-	    drm_intel_gem_bo_unmap_gtt(bo);
-	else
-	    drm_intel_bo_unpin(bo);
-	pixmap->devPrivate.ptr = NULL;
-    }
-}
-
-void
-i830_uxa_block_handler (ScreenPtr screen)
-{
-    ScrnInfoPtr scrn = xf86Screens[screen->myNum];
-    I830Ptr i830 = I830PTR(scrn);
-
-    if (i830->need_flush) {
-	dri_bo_wait_rendering (i830->front_buffer->bo);
-	i830->need_flush = FALSE;
-    }
-}
-
-static Bool
 i830_uxa_pixmap_is_offscreen(PixmapPtr pixmap)
 {
     ScreenPtr screen = pixmap->drawable.pScreen;
@@ -1083,8 +1001,8 @@ i830_uxa_init (ScreenPtr pScreen)
  	i830->uxa_driver->done_composite = i830_done_composite;
     }
 
-    i830->uxa_driver->prepare_access = i830_uxa_prepare_access;
-    i830->uxa_driver->finish_access = i830_uxa_finish_access;
+    i830->uxa_driver->prepare_access = i830_prepare_access;
+    i830->uxa_driver->finish_access = i830_finish_access;
     i830->uxa_driver->pixmap_is_offscreen = i830_uxa_pixmap_is_offscreen;
 
     if(!uxa_driver_init(pScreen, i830->uxa_driver)) {
@@ -1119,9 +1037,11 @@ extern void ExaOffscreenMarkUsed(PixmapPtr);
 unsigned long long
 I830TexOffsetStart(PixmapPtr pPix)
 {
-    exaMoveInPixmap(pPix);
-    ExaOffscreenMarkUsed(pPix);
+    dri_bo *bo = i830_get_pixmap_bo(pPix);
+
+    if (!bo)
+	return 0;
 
-    return exaGetPixmapOffset(pPix);
+    return bo->offset;
 }
 #endif
diff --git a/src/i915_render.c b/src/i915_render.c
index 268dd8a..4c810a1 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -322,6 +322,9 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
 	i830_get_pixmap_bo(pDst),
     };
 
+    if (!pScrn->vtSema)
+	return FALSE;
+
     i830_exa_check_pitch_3d(pSrc);
     if (pMask)
 	i830_exa_check_pitch_3d(pMask);
diff --git a/src/i965_render.c b/src/i965_render.c
index c123a36..5717ca8 100644
--- a/src/i965_render.c
+++ b/src/i965_render.c
@@ -1265,6 +1265,9 @@ i965_prepare_composite(int op, PicturePtr pSrcPicture,
     uint32_t *binding_table;
     drm_intel_bo *binding_table_bo, *surface_state_bo;
 
+    if (!pScrn->vtSema)
+	return FALSE;
+
     if (composite_op->src_filter < 0)
 	I830FALLBACK("Bad src filter 0x%x\n", pSrcPicture->filter);
     composite_op->src_extend =



More information about the Intel-gfx mailing list