Beispiel #1
0
/* Update the hardware state.  This is called if another context has
 * grabbed the hardware lock, which includes the X server.  This
 * function also updates the driver's window state after the X server
 * moves, resizes or restacks a window -- the change will be reflected
 * in the drawable position and clip rects.  Since the X server grabs
 * the hardware lock when it changes the window state, this routine will
 * automatically be called after such a change.
 */
void radeonGetLock(radeonContextPtr rmesa, GLuint flags)
{
	__DRIdrawablePrivate *const drawable = radeon_get_drawable(rmesa);
	__DRIdrawablePrivate *const readable = radeon_get_readable(rmesa);
	__DRIscreenPrivate *sPriv = rmesa->dri.screen;

	drmGetLock(rmesa->dri.fd, rmesa->dri.hwContext, flags);

	/* The window might have moved, so we might need to get new clip
	 * rects.
	 *
	 * NOTE: This releases and regrabs the hw lock to allow the X server
	 * to respond to the DRI protocol request for new drawable info.
	 * Since the hardware state depends on having the latest drawable
	 * clip rects, all state checking must be done _after_ this call.
	 */
	if (drawable)
		DRI_VALIDATE_DRAWABLE_INFO(sPriv, drawable);
	if (readable && drawable != readable) {
		DRI_VALIDATE_DRAWABLE_INFO(sPriv, readable);
	}

	if (drawable && (rmesa->lastStamp != drawable->lastStamp)) {
		radeon_window_moved(rmesa);
		rmesa->lastStamp = drawable->lastStamp;
	}

	rmesa->vtbl.get_lock(rmesa);
}
Beispiel #2
0
void tdfxGetLock( tdfxContextPtr fxMesa )
{
    __DRIcontextPrivate *cPriv = fxMesa->driContext;
    __DRIdrawablePrivate *const drawable = cPriv->driDrawablePriv;
    __DRIdrawablePrivate *const readable = cPriv->driReadablePriv;
    __DRIscreenPrivate *sPriv = drawable->driScreenPriv;
    TDFXSAREAPriv *saPriv = (TDFXSAREAPriv *) (((char *) sPriv->pSAREA) +
					fxMesa->fxScreen->sarea_priv_offset);
    unsigned int stamp = drawable->lastStamp;

    drmGetLock( fxMesa->driFd, fxMesa->hHWContext, 0 );

    /* This macro will update drawable's cliprects if needed */
    DRI_VALIDATE_DRAWABLE_INFO(sPriv, drawable);
    if (drawable != readable) {
	DRI_VALIDATE_DRAWABLE_INFO(sPriv, readable);
    }

    if ( saPriv->fifoOwner != fxMesa->hHWContext ) {
        fxMesa->Glide.grDRIImportFifo( saPriv->fifoPtr, saPriv->fifoRead );
    }

    if ( saPriv->ctxOwner != fxMesa->hHWContext ) {
        /* This sequence looks a little odd. Glide mirrors the state, and
	 * when you get the state you are forcing the mirror to be up to
	 * date, and then getting a copy from the mirror. You can then force
	 * that state onto the hardware when you set the state.
	 */
        void *state;
        FxI32 stateSize;
        fxMesa->Glide.grGet(GR_GLIDE_STATE_SIZE, 4, &stateSize);
        state = malloc(stateSize);
        fxMesa->Glide.grGlideGetState( state );
        fxMesa->Glide.grGlideSetState( state );
        free( state );
    }

#if 0
    if ( saPriv->texOwner != fxMesa->hHWContext ) {
        tdfxTMRestoreTextures_NoLock( fxMesa );
    }
#endif

    if ((*drawable->pStamp != stamp)
	|| (saPriv->ctxOwner != fxMesa->hHWContext)) {
       driUpdateFramebufferSize(fxMesa->glCtx, drawable);
       if (drawable != readable) {
	   driUpdateFramebufferSize(fxMesa->glCtx, readable);
       }

       tdfxUpdateClipping(fxMesa->glCtx);
       tdfxUploadClipping(fxMesa);
    }

    DEBUG_LOCK();
}
Beispiel #3
0
/* Update the hardware state.  This is called if another context has
 * grabbed the hardware lock, which includes the X server.  This
 * function also updates the driver's window state after the X server
 * moves, resizes or restacks a window -- the change will be reflected
 * in the drawable position and clip rects.  Since the X server grabs
 * the hardware lock when it changes the window state, this routine will
 * automatically be called after such a change.
 */
void
sisGetLock( sisContextPtr smesa, GLuint flags )
{
   __DRIdrawablePrivate *dPriv = smesa->driDrawable;
   __DRIscreenPrivate *sPriv = smesa->driScreen;
   SISSAREAPrivPtr sarea = smesa->sarea;

   drmGetLock( smesa->driFd, smesa->hHWContext, flags );

   /* The window might have moved, so we might need to get new clip
    * rects.
    *
    * NOTE: This releases and regrabs the hw lock to allow the X server
    * to respond to the DRI protocol request for new drawable info.
    * Since the hardware state depends on having the latest drawable
    * clip rects, all state checking must be done _after_ this call.
    */
   DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );

   if ( smesa->lastStamp != dPriv->lastStamp ) {
      sisUpdateBufferSize( smesa );
      sisUpdateClipping( smesa->glCtx );
      sisDDDrawBuffer( smesa->glCtx, smesa->glCtx->Color.DrawBuffer );
      smesa->lastStamp = dPriv->lastStamp;
   }

   if ( sarea->CtxOwner != smesa->hHWContext ) {
      sarea->CtxOwner = smesa->hHWContext;
      smesa->GlobalFlag = GFLAG_ALL;
   }
}
Beispiel #4
0
/* Update the hardware state.  This is called if another context has
 * grabbed the hardware lock, which includes the X server.  This
 * function also updates the driver's window state after the X server
 * moves, resizes or restacks a window -- the change will be reflected
 * in the drawable position and clip rects.  Since the X server grabs
 * the hardware lock when it changes the window state, this routine will
 * automatically be called after such a change.
 */
void radeonGetLock(radeonContextPtr radeon, GLuint flags)
{
	__DRIdrawablePrivate *dPriv = radeon->dri.drawable;
	__DRIscreenPrivate *sPriv = radeon->dri.screen;
	drm_radeon_sarea_t *sarea = radeon->sarea;

	drmGetLock(radeon->dri.fd, radeon->dri.hwContext, flags);

	/* The window might have moved, so we might need to get new clip
	 * rects.
	 *
	 * NOTE: This releases and regrabs the hw lock to allow the X server
	 * to respond to the DRI protocol request for new drawable info.
	 * Since the hardware state depends on having the latest drawable
	 * clip rects, all state checking must be done _after_ this call.
	 */
	DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);

	if (sarea->ctx_owner != radeon->dri.hwContext)
		sarea->ctx_owner = radeon->dri.hwContext;

	if (IS_FAMILY_R300(radeon))
		r300RegainedLock(radeon);
#if R200_MERGED
	else
		r200RegainedLock((r200ContextPtr)radeon);
#endif
	
	radeon->lost_context = GL_TRUE;
}
Beispiel #5
0
/* Update the hardware state.  This is called if another context has
 * grabbed the hardware lock, which includes the X server.  This
 * function also updates the driver's window state after the X server
 * moves, resizes or restacks a window -- the change will be reflected
 * in the drawable position and clip rects.  Since the X server grabs
 * the hardware lock when it changes the window state, this routine will
 * automatically be called after such a change.
 */
void radeonGetLock(radeonContextPtr rmesa, GLuint flags)
{
    __DRIdrawablePrivate *const drawable = rmesa->dri.drawable;
    __DRIdrawablePrivate *const readable = rmesa->dri.readable;
    __DRIscreenPrivate *sPriv = rmesa->dri.screen;
    drm_radeon_sarea_t *sarea = rmesa->sarea;
    r300ContextPtr r300 = (r300ContextPtr) rmesa;

    assert(drawable != NULL);

    drmGetLock(rmesa->dri.fd, rmesa->dri.hwContext, flags);

    /* The window might have moved, so we might need to get new clip
     * rects.
     *
     * NOTE: This releases and regrabs the hw lock to allow the X server
     * to respond to the DRI protocol request for new drawable info.
     * Since the hardware state depends on having the latest drawable
     * clip rects, all state checking must be done _after_ this call.
     */
    DRI_VALIDATE_DRAWABLE_INFO(sPriv, drawable);
    if (drawable != readable) {
        DRI_VALIDATE_DRAWABLE_INFO(sPriv, readable);
    }

    if (rmesa->lastStamp != drawable->lastStamp) {
        radeonUpdatePageFlipping(rmesa);
        radeonSetCliprects(rmesa);
        r300UpdateViewportOffset(rmesa->glCtx);
        driUpdateFramebufferSize(rmesa->glCtx, drawable);
    }

    if (sarea->ctx_owner != rmesa->dri.hwContext) {
        int i;

        sarea->ctx_owner = rmesa->dri.hwContext;
        for (i = 0; i < r300->nr_heaps; i++) {
            DRI_AGE_TEXTURES(r300->texture_heaps[i]);
        }
    }

    rmesa->lost_context = GL_TRUE;
}
Beispiel #6
0
/* Update the hardware state.  This is called if another context has
 * grabbed the hardware lock, which includes the X server.  This
 * function also updates the driver's window state after the X server
 * moves, resizes or restacks a window -- the change will be reflected
 * in the drawable position and clip rects.  Since the X server grabs
 * the hardware lock when it changes the window state, this routine will
 * automatically be called after such a change.
 */
void mach64GetLock( mach64ContextPtr mmesa, GLuint flags )
{
   __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
   __DRIscreenPrivate *sPriv = mmesa->driScreen;
   drm_mach64_sarea_t *sarea = mmesa->sarea;
   int i;

   drmGetLock( mmesa->driFd, mmesa->hHWContext, flags );

   /* The window might have moved, so we might need to get new clip
    * rects.
    *
    * NOTE: This releases and regrabs the hw lock to allow the X server
    * to respond to the DRI protocol request for new drawable info.
    * Since the hardware state depends on having the latest drawable
    * clip rects, all state checking must be done _after_ this call.
    */
   DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv ); 

   if ( mmesa->lastStamp != dPriv->lastStamp ) {
      mmesa->lastStamp = dPriv->lastStamp;
      if (mmesa->glCtx->DrawBuffer->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT)
         mach64SetCliprects( mmesa->glCtx, GL_BACK_LEFT );
      else
         mach64SetCliprects( mmesa->glCtx, GL_FRONT_LEFT );
      driUpdateFramebufferSize( mmesa->glCtx, dPriv );
      mach64CalcViewport( mmesa->glCtx );
   }

   mmesa->dirty |= (MACH64_UPLOAD_CONTEXT
		    | MACH64_UPLOAD_MISC
		    | MACH64_UPLOAD_CLIPRECTS);

   /* EXA render acceleration uses the texture engine, so restore it */
   mmesa->dirty |= (MACH64_UPLOAD_TEXTURE);

   if ( sarea->ctx_owner != mmesa->hHWContext ) {
      sarea->ctx_owner = mmesa->hHWContext;
      mmesa->dirty = MACH64_UPLOAD_ALL;
   }

   for ( i = mmesa->firstTexHeap ; i < mmesa->lastTexHeap ; i++ ) {
      DRI_AGE_TEXTURES( mmesa->texture_heaps[i] );
   }
}
Beispiel #7
0
/* Update the hardware state.  This is called if another context has
 * grabbed the hardware lock, which includes the X server.  This
 * function also updates the driver's window state after the X server
 * moves, resizes or restacks a window -- the change will be reflected
 * in the drawable position and clip rects.  Since the X server grabs
 * the hardware lock when it changes the window state, this routine will
 * automatically be called after such a change.
 */
void r200GetLock( r200ContextPtr rmesa, GLuint flags )
{
   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
   __DRIscreenPrivate *sPriv = rmesa->dri.screen;
   drm_radeon_sarea_t *sarea = rmesa->sarea;
   int i;

   drmGetLock( rmesa->dri.fd, rmesa->dri.hwContext, flags );

   /* The window might have moved, so we might need to get new clip
    * rects.
    *
    * NOTE: This releases and regrabs the hw lock to allow the X server
    * to respond to the DRI protocol request for new drawable info.
    * Since the hardware state depends on having the latest drawable
    * clip rects, all state checking must be done _after_ this call.
    */
   DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );

   if ( rmesa->lastStamp != dPriv->lastStamp ) {
      r200UpdatePageFlipping( rmesa );
      if (rmesa->glCtx->DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT)
         r200SetCliprects( rmesa, GL_BACK_LEFT );
      else
         r200SetCliprects( rmesa, GL_FRONT_LEFT );
      r200UpdateViewportOffset( rmesa->glCtx );
      rmesa->lastStamp = dPriv->lastStamp;
   }

   R200_STATECHANGE( rmesa, ctx );
   if (rmesa->sarea->tiling_enabled) {
      rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
   }
   else rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] &= ~R200_COLOR_TILE_ENABLE;

   if ( sarea->ctx_owner != rmesa->dri.hwContext ) {
      sarea->ctx_owner = rmesa->dri.hwContext;
   }

   for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
      DRI_AGE_TEXTURES( rmesa->texture_heaps[ i ] );
   }

   rmesa->lost_context = GL_TRUE;
}
Beispiel #8
0
/* Update the hardware state.  This is called if another main/context.has
 * grabbed the hardware lock, which includes the X server.  This
 * function also updates the driver's window state after the X server
 * moves, resizes or restacks a window -- the change will be reflected
 * in the drawable position and clip rects.  Since the X server grabs
 * the hardware lock when it changes the window state, this routine will
 * automatically be called after such a change.
 */
void r128GetLock( r128ContextPtr rmesa, GLuint flags )
{
   __DRIdrawable *dPriv = rmesa->driDrawable;
   __DRIscreen *sPriv = rmesa->driScreen;
   drm_r128_sarea_t *sarea = rmesa->sarea;
   int i;

   drmGetLock( rmesa->driFd, rmesa->hHWContext, flags );

   /* The window might have moved, so we might need to get new clip
    * rects.
    *
    * NOTE: This releases and regrabs the hw lock to allow the X server
    * to respond to the DRI protocol request for new drawable info.
    * Since the hardware state depends on having the latest drawable
    * clip rects, all state checking must be done _after_ this call.
    */
   DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );

   if ( rmesa->lastStamp != dPriv->lastStamp ) {
      r128UpdatePageFlipping( rmesa );
      driUpdateFramebufferSize(rmesa->glCtx, dPriv);
      rmesa->lastStamp = dPriv->lastStamp;
      rmesa->new_state |= R128_NEW_CLIP;
      RENDERINPUTS_ONES( rmesa->tnl_state_bitset );
   }

   rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_CLIPRECTS;

   rmesa->numClipRects = dPriv->numClipRects;
   rmesa->pClipRects = dPriv->pClipRects;

   if ( sarea->ctx_owner != rmesa->hHWContext ) {
      sarea->ctx_owner = rmesa->hHWContext;
      rmesa->dirty = R128_UPLOAD_ALL;
   }

   for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
      DRI_AGE_TEXTURES( rmesa->texture_heaps[i] );
   }
}
Beispiel #9
0
/* Update the hardware state.  This is called if another context has
 * grabbed the hardware lock, which includes the X server.  This
 * function also updates the driver's window state after the X server
 * moves, resizes or restacks a window -- the change will be reflected
 * in the drawable position and clip rects.  Since the X server grabs
 * the hardware lock when it changes the window state, this routine will
 * automatically be called after such a change.
 */
void gammaGetLock( gammaContextPtr gmesa, GLuint flags )
{
   __DRIdrawablePrivate *dPriv = gmesa->driDrawable;
   __DRIscreenPrivate *sPriv = gmesa->driScreen;

   drmGetLock( gmesa->driFd, gmesa->hHWContext, flags );

   /* The window might have moved, so we might need to get new clip
    * rects.
    *
    * NOTE: This releases and regrabs the hw lock to allow the X server
    * to respond to the DRI protocol request for new drawable info.
    * Since the hardware state depends on having the latest drawable
    * clip rects, all state checking must be done _after_ this call.
    */
   DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );

   if ( gmesa->lastStamp != dPriv->lastStamp ) {
      driUpdateFramebufferSize(gmesa->glCtx, dPriv);
      gmesa->lastStamp = dPriv->lastStamp;
      gmesa->new_state |= GAMMA_NEW_WINDOW | GAMMA_NEW_CLIP;
   }

   gmesa->numClipRects = dPriv->numClipRects;
   gmesa->pClipRects = dPriv->pClipRects;

#if 0
   gmesa->dirty = ~0;

   if ( sarea->ctxOwner != gmesa->hHWContext ) {
      sarea->ctxOwner = gmesa->hHWContext;
      gmesa->dirty = GAMMA_UPLOAD_ALL;
   }

   for ( i = 0 ; i < gmesa->lastTexHeap ; i++ ) {
      if ( sarea->texAge[i] != gmesa->lastTexAge[i] ) {
	 gammaAgeTextures( gmesa, i );
      }
   }
#endif
}
Beispiel #10
0
void mgaUpdateRects( mgaContextPtr mmesa, GLuint buffers )
{
   __DRIdrawablePrivate *driDrawable = mmesa->driDrawable;
   drm_mga_sarea_t *sarea = mmesa->sarea;


   DRI_VALIDATE_DRAWABLE_INFO(mmesa->driScreen, driDrawable); 
   mmesa->dirty_cliprects = 0;	

   if (mmesa->draw_buffer == MGA_FRONT)
      mgaXMesaSetFrontClipRects( mmesa );
   else
      mgaXMesaSetBackClipRects( mmesa );

   sarea->req_drawable = driDrawable->draw;
   sarea->req_draw_buffer = mmesa->draw_buffer;

   mgaUpdateClipping( mmesa->glCtx );
   mgaCalcViewport( mmesa->glCtx );

   mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
}
Beispiel #11
0
/* Update the hardware state.  This is called if another context has
 * grabbed the hardware lock, which includes the X server.  This
 * function also updates the driver's window state after the X server
 * moves, resizes or restacks a window -- the change will be reflected
 * in the drawable position and clip rects.  Since the X server grabs
 * the hardware lock when it changes the window state, this routine will
 * automatically be called after such a change.
 */
void nouveauGetLock( nouveauContextPtr nmesa, GLuint flags )
{
   __DRIdrawablePrivate *dPriv = nmesa->driDrawable;
   __DRIscreenPrivate *sPriv = nmesa->driScreen;
   drm_nouveau_sarea_t *sarea = nmesa->sarea;

   drmGetLock( nmesa->driFd, nmesa->hHWContext, flags );

   /* The window might have moved, so we might need to get new clip
    * rects.
    *
    * NOTE: This releases and regrabs the hw lock to allow the X server
    * to respond to the DRI protocol request for new drawable info.
    * Since the hardware state depends on having the latest drawable
    * clip rects, all state checking must be done _after_ this call.
    */
   DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );

   /* If timestamps don't match, the window has been changed */
   if (nmesa->lastStamp != dPriv->lastStamp) {
      struct gl_framebuffer *fb = (struct gl_framebuffer *)dPriv->driverPrivate;

      /* _mesa_resize_framebuffer will take care of calling the renderbuffer's
       * AllocStorage function if we need more memory to hold it */
      if (fb->Width != dPriv->w || fb->Height != dPriv->h) {
	 _mesa_resize_framebuffer(nmesa->glCtx, fb, dPriv->w, dPriv->h);
	 /* resize buffers, will call nouveau_window_moved */
	 nouveau_build_framebuffer(nmesa->glCtx, fb);
      } else {
	 nouveau_window_moved(nmesa->glCtx);
      }

      nmesa->lastStamp = dPriv->lastStamp;
   }

   nmesa->numClipRects = dPriv->numClipRects;
   nmesa->pClipRects = dPriv->pClipRects;

}
Beispiel #12
0
/* Update the hardware state.  This is called if another context has
 * grabbed the hardware lock, which includes the X server.  This
 * function also updates the driver's window state after the X server
 * moves, resizes or restacks a window -- the change will be reflected
 * in the drawable position and clip rects.  Since the X server grabs
 * the hardware lock when it changes the window state, this routine will
 * automatically be called after such a change.
 */
void radeonGetLock( radeonContextPtr rmesa, GLuint flags )
{
   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
   __DRIscreenPrivate *sPriv = rmesa->dri.screen;
   RADEONSAREAPrivPtr sarea = rmesa->sarea;
   int i;

   drmGetLock( rmesa->dri.fd, rmesa->dri.hwContext, flags );

   /* The window might have moved, so we might need to get new clip
    * rects.
    *
    * NOTE: This releases and regrabs the hw lock to allow the X server
    * to respond to the DRI protocol request for new drawable info.
    * Since the hardware state depends on having the latest drawable
    * clip rects, all state checking must be done _after_ this call.
    */
   DRI_VALIDATE_DRAWABLE_INFO( rmesa->dri.display, sPriv, dPriv );

   if ( rmesa->lastStamp != dPriv->lastStamp ) {
      radeonUpdatePageFlipping( rmesa );
      radeonSetCliprects( rmesa, rmesa->glCtx->Color.DriverDrawBuffer );
      radeonUpdateViewportOffset( rmesa->glCtx );
      rmesa->lastStamp = dPriv->lastStamp;
   }

   if ( sarea->ctxOwner != rmesa->dri.hwContext ) {
      sarea->ctxOwner = rmesa->dri.hwContext;

      for ( i = 0 ; i < rmesa->texture.numHeaps ; i++ ) {
	 if ( rmesa->texture.heap[i] && sarea->texAge[i] != rmesa->texture.age[i] ) {
	    radeonAgeTextures( rmesa, i );
	 }
      }
   }
}
Beispiel #13
0
/**
 * Display a colorbuffer surface in an X window.
 * Used for SwapBuffers and flushing front buffer rendering.
 *
 * \param dPriv  the window/drawable to display into
 * \param surf  the surface to display
 * \param rect  optional subrect of surface to display (may be NULL).
 */
void
intelDisplaySurface(__DRIdrawablePrivate *dPriv,
                    struct pipe_surface *surf,
                    const drm_clip_rect_t *rect)
{
   struct intel_screen *intelScreen = intel_screen(dPriv->driScreenPriv);
   struct intel_context *intel = intelScreen->dummyContext;

   DBG(SWAP, "%s\n", __FUNCTION__);

   if (!intel) {
      /* XXX this is where some kind of extra/meta context could be useful */
      return;
   }

   if (intel->last_swap_fence) {
      driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, TRUE);
      driFenceUnReference(&intel->last_swap_fence);
      intel->last_swap_fence = NULL;
   }
   intel->last_swap_fence = intel->first_swap_fence;
   intel->first_swap_fence = NULL;

   /* The LOCK_HARDWARE is required for the cliprects.  Buffer offsets
    * should work regardless.
    */
   LOCK_HARDWARE(intel);
   /* if this drawable isn't currently bound the LOCK_HARDWARE done on the
    * current context (which is what intelScreenContext should return) might
    * not get a contended lock and thus cliprects not updated (tests/manywin)
    */
   if (intel_context(dPriv->driContextPriv) != intel)
      DRI_VALIDATE_DRAWABLE_INFO(intel->driScreen, dPriv);


   if (dPriv && dPriv->numClipRects) {
      const int srcWidth = surf->width;
      const int srcHeight = surf->height;
      const int nbox = dPriv->numClipRects;
      const drm_clip_rect_t *pbox = dPriv->pClipRects;
      const int pitch = intelScreen->front.pitch / intelScreen->front.cpp;
      const int cpp = intelScreen->front.cpp;
      const int srcpitch = surf->stride / cpp;
      int BR13, CMD;
      int i;

      ASSERT(surf->buffer);
      ASSERT(surf->cpp == cpp);

      DBG(SWAP, "screen pitch %d  src surface pitch %d\n",
	  pitch, surf->stride);

      if (cpp == 2) {
	 BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
	 CMD = XY_SRC_COPY_BLT_CMD;
      }
      else {
	 BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25);
	 CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
		XY_SRC_COPY_BLT_WRITE_RGB);
      }

      for (i = 0; i < nbox; i++, pbox++) {
	 drm_clip_rect_t box;
	 drm_clip_rect_t sbox;

	 if (pbox->x1 > pbox->x2 ||
	     pbox->y1 > pbox->y2 ||
	     pbox->x2 > intelScreen->front.width ||
	     pbox->y2 > intelScreen->front.height) {
            /* invalid cliprect, skip it */
	    continue;
         }

	 box = *pbox;

	 if (rect) {
            /* intersect cliprect with user-provided src rect */
	    drm_clip_rect_t rrect;

	    rrect.x1 = dPriv->x + rect->x1;
	    rrect.y1 = (dPriv->h - rect->y1 - rect->y2) + dPriv->y;
	    rrect.x2 = rect->x2 + rrect.x1;
	    rrect.y2 = rect->y2 + rrect.y1;
	    if (rrect.x1 > box.x1)
	       box.x1 = rrect.x1;
	    if (rrect.y1 > box.y1)
	       box.y1 = rrect.y1;
	    if (rrect.x2 < box.x2)
	       box.x2 = rrect.x2;
	    if (rrect.y2 < box.y2)
	       box.y2 = rrect.y2;

	    if (box.x1 > box.x2 || box.y1 > box.y2)
	       continue;
	 }

	 /* restrict blit to size of actually rendered area */
	 if (box.x2 - box.x1 > srcWidth)
	    box.x2 = srcWidth + box.x1;
	 if (box.y2 - box.y1 > srcHeight)
	    box.y2 = srcHeight + box.y1;

	 DBG(SWAP, "box x1 x2 y1 y2 %d %d %d %d\n",
	     box.x1, box.x2, box.y1, box.y2);

	 sbox.x1 = box.x1 - dPriv->x;
	 sbox.y1 = box.y1 - dPriv->y;

         assert(box.x1 < box.x2);
         assert(box.y1 < box.y2);

         /* XXX this could be done with pipe->surface_copy() */
	 /* XXX should have its own batch buffer */
	 if (!BEGIN_BATCH(8, 2)) {
	    /*
	     * Since we share this batch buffer with a context
	     * we can't flush it since that risks a GPU lockup
	     */
	    assert(0);
	    continue;
	 }

	 OUT_BATCH(CMD);
	 OUT_BATCH(BR13);
	 OUT_BATCH((box.y1 << 16) | box.x1);
	 OUT_BATCH((box.y2 << 16) | box.x2);

	 OUT_RELOC(intelScreen->front.buffer,
		   DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
		   DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
	 OUT_BATCH((sbox.y1 << 16) | sbox.x1);
	 OUT_BATCH((srcpitch * cpp) & 0xffff);
	 OUT_RELOC(dri_bo(surf->buffer),
                   DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
		   DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0);

      }

      if (intel->first_swap_fence)
	 driFenceUnReference(&intel->first_swap_fence);
      intel->first_swap_fence = intel_be_batchbuffer_flush(intel->base.batch);
   }

   UNLOCK_HARDWARE(intel);

   if (intel->lastStamp != dPriv->lastStamp) {
      intelUpdateWindowSize(dPriv);
      intel->lastStamp = dPriv->lastStamp;
   }
}