diff --git a/exa/exa.c b/exa/exa.c index 29a94b31d..92ff394e2 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -78,6 +78,21 @@ exaGetPixmapPitch(PixmapPtr pPix) return pPix->devKind; } +/* Returns the size in bytes of the given pixmap in + * video memory. Only valid when the vram storage has been + * allocated + */ +unsigned long +exaGetPixmapSize(PixmapPtr pPix) +{ + ExaPixmapPrivPtr pExaPixmap; + + pExaPixmap = ExaGetPixmapPriv(pPix); + if (pExaPixmap != NULL) + return pExaPixmap->size; + return 0; +} + void exaDrawableDirty (DrawablePtr pDrawable) { @@ -185,6 +200,7 @@ exaPixmapAllocArea (PixmapPtr pPixmap) pitch = (w * bpp / 8) + (pExaScr->info->card.pixmapPitchAlign - 1); pitch -= pitch % pExaScr->info->card.pixmapPitchAlign; + pExaPixmap->size = pitch * h; pExaPixmap->devKind = pPixmap->devKind; pExaPixmap->devPrivate = pPixmap->devPrivate; pExaPixmap->area = exaOffscreenAlloc (pScreen, pitch * h, @@ -439,6 +455,7 @@ exaDrawableIsOffscreen (DrawablePtr pDrawable) { PixmapPtr pPixmap; STRACE; + if (pDrawable->type == DRAWABLE_WINDOW) pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); else @@ -446,6 +463,57 @@ exaDrawableIsOffscreen (DrawablePtr pDrawable) return exaPixmapIsOffscreen (pPixmap); } +void +exaPrepareAccess(DrawablePtr pDrawable, int index) +{ + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv (pScreen); + PixmapPtr pPixmap; + STRACE; + + if (pDrawable->type == DRAWABLE_WINDOW) + pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); + else + pPixmap = (PixmapPtr) pDrawable; + + if (index == EXA_PREPARE_DEST) + exaDrawableDirty (pDrawable); + if (exaPixmapIsOffscreen (pPixmap)) + exaWaitSync (pDrawable->pScreen); + else + return; + + if (pExaScr->info->accel.PrepareAccess == NULL) + return; + + if (!(*pExaScr->info->accel.PrepareAccess) (pPixmap, index)) { + ExaPixmapPriv (pPixmap); + assert (pExaPixmap->score != EXA_PIXMAP_SCORE_PINNED); + exaMoveOutPixmap (pPixmap); + } +} + +void +exaFinishAccess(DrawablePtr pDrawable, int index) +{ + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv (pScreen); + PixmapPtr pPixmap; + STRACE; + + if (pExaScr->info->accel.FinishAccess == NULL) + return; + + if (pDrawable->type == DRAWABLE_WINDOW) + pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); + else + pPixmap = (PixmapPtr) pDrawable; + if (!exaPixmapIsOffscreen (pPixmap)) + return; + + (*pExaScr->info->accel.FinishAccess) (pPixmap, index); +} + #if 0 static void exaFillTiled(int dst_x, @@ -620,10 +688,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, exaPixmapUseMemory ((PixmapPtr) pSrcDrawable); if (pDstDrawable->type == DRAWABLE_PIXMAP) exaPixmapUseMemory ((PixmapPtr) pDstDrawable); - exaWaitSync (pDstDrawable->pScreen); - fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, - pbox, nbox, dx, dy, reverse, upsidedown, - bitplane, closure); + goto fallback; } /* If either drawable is already in framebuffer, try to get both of them @@ -664,15 +729,18 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, } (*pExaScr->info->accel.DoneCopy) (pDstPixmap); exaMarkSync(pDstDrawable->pScreen); + exaDrawableDirty (pDstDrawable); + return; } - else - { - exaWaitSync (pDstDrawable->pScreen); - fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, - pbox, nbox, dx, dy, reverse, upsidedown, - bitplane, closure); - } - exaDrawableDirty (pDstDrawable); + +fallback: + exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST); + exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC); + fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, + pbox, nbox, dx, dy, reverse, upsidedown, + bitplane, closure); + exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC); + exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST); } RegionPtr @@ -822,12 +890,12 @@ exaSolidBoxClipped (DrawablePtr pDrawable, !(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) || !(*pExaScr->info->accel.PrepareSolid) (pPixmap, GXcopy, pm, fg)) { - exaWaitSync (pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel); fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2, fbAnd (GXcopy, fg, pm), fbXor (GXcopy, fg, pm)); - exaDrawableDirty (pDrawable); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); return; } for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); @@ -949,8 +1017,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable, opaque = FALSE; } - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); ppci = ppciInit; while (nglyph--) @@ -996,6 +1063,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable, } x += pci->metrics.characterWidth; } + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } static const GCOps exaOps = { @@ -1121,14 +1189,15 @@ exaFillRegionSolid (DrawablePtr pDrawable, } (*pExaScr->info->accel.DoneSolid) (pPixmap); exaMarkSync(pDrawable->pScreen); + exaDrawableDirty (pDrawable); } else { - exaWaitSync (pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbFillRegionSolid (pDrawable, pRegion, 0, fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } - exaDrawableDirty (pDrawable); } static void diff --git a/exa/exa.h b/exa/exa.h index 2cf9fe44a..5e850a3cf 100644 --- a/exa/exa.h +++ b/exa/exa.h @@ -175,6 +175,24 @@ typedef struct _ExaAccelInfo { */ int (*MarkSync) (ScreenPtr pScreen); void (*WaitMarker) (ScreenPtr pScreen, int marker); + + /* These are wrapping all fb or composite operations that will cause + * a direct access to the framebuffer. You can use them to update + * endian swappers, force migration to RAM, or whatever else you find + * useful at this point. EXA can stack up to 3 calls to Prepare/Finish + * access, though they will have a different index. If your hardware + * doesn't have enough separate configurable swapper, you can return + * FALSE from PrepareAccess() to force EXA to migrate the pixmap to RAM. + * Note that DownloadFromScreen and UploadToScreen can both be called + * between PrepareAccess() and FinishAccess(). If they need to use a + * swapper, they should save & restore its setting. + */ + Bool (*PrepareAccess)(PixmapPtr pPix, int index); + void (*FinishAccess)(PixmapPtr pPix, int index); + #define EXA_PREPARE_DEST 0 + #define EXA_PREPARE_SRC 1 + #define EXA_PREPARE_MASK 2 + } ExaAccelInfoRec, *ExaAccelInfoPtr; typedef struct _ExaDriver { @@ -224,6 +242,9 @@ exaGetPixmapOffset(PixmapPtr pPix); unsigned long exaGetPixmapPitch(PixmapPtr pPix); +unsigned long +exaGetPixmapSize(PixmapPtr pPix); + #define exaInitCard(exa, sync, memory_base, off_screen_base, memory_size, \ offscreen_byte_align, offscreen_pitch, flags, \ max_x, max_y) \ diff --git a/exa/exa_accel.c b/exa/exa_accel.c index 29a94b31d..92ff394e2 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -78,6 +78,21 @@ exaGetPixmapPitch(PixmapPtr pPix) return pPix->devKind; } +/* Returns the size in bytes of the given pixmap in + * video memory. Only valid when the vram storage has been + * allocated + */ +unsigned long +exaGetPixmapSize(PixmapPtr pPix) +{ + ExaPixmapPrivPtr pExaPixmap; + + pExaPixmap = ExaGetPixmapPriv(pPix); + if (pExaPixmap != NULL) + return pExaPixmap->size; + return 0; +} + void exaDrawableDirty (DrawablePtr pDrawable) { @@ -185,6 +200,7 @@ exaPixmapAllocArea (PixmapPtr pPixmap) pitch = (w * bpp / 8) + (pExaScr->info->card.pixmapPitchAlign - 1); pitch -= pitch % pExaScr->info->card.pixmapPitchAlign; + pExaPixmap->size = pitch * h; pExaPixmap->devKind = pPixmap->devKind; pExaPixmap->devPrivate = pPixmap->devPrivate; pExaPixmap->area = exaOffscreenAlloc (pScreen, pitch * h, @@ -439,6 +455,7 @@ exaDrawableIsOffscreen (DrawablePtr pDrawable) { PixmapPtr pPixmap; STRACE; + if (pDrawable->type == DRAWABLE_WINDOW) pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); else @@ -446,6 +463,57 @@ exaDrawableIsOffscreen (DrawablePtr pDrawable) return exaPixmapIsOffscreen (pPixmap); } +void +exaPrepareAccess(DrawablePtr pDrawable, int index) +{ + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv (pScreen); + PixmapPtr pPixmap; + STRACE; + + if (pDrawable->type == DRAWABLE_WINDOW) + pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); + else + pPixmap = (PixmapPtr) pDrawable; + + if (index == EXA_PREPARE_DEST) + exaDrawableDirty (pDrawable); + if (exaPixmapIsOffscreen (pPixmap)) + exaWaitSync (pDrawable->pScreen); + else + return; + + if (pExaScr->info->accel.PrepareAccess == NULL) + return; + + if (!(*pExaScr->info->accel.PrepareAccess) (pPixmap, index)) { + ExaPixmapPriv (pPixmap); + assert (pExaPixmap->score != EXA_PIXMAP_SCORE_PINNED); + exaMoveOutPixmap (pPixmap); + } +} + +void +exaFinishAccess(DrawablePtr pDrawable, int index) +{ + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv (pScreen); + PixmapPtr pPixmap; + STRACE; + + if (pExaScr->info->accel.FinishAccess == NULL) + return; + + if (pDrawable->type == DRAWABLE_WINDOW) + pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); + else + pPixmap = (PixmapPtr) pDrawable; + if (!exaPixmapIsOffscreen (pPixmap)) + return; + + (*pExaScr->info->accel.FinishAccess) (pPixmap, index); +} + #if 0 static void exaFillTiled(int dst_x, @@ -620,10 +688,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, exaPixmapUseMemory ((PixmapPtr) pSrcDrawable); if (pDstDrawable->type == DRAWABLE_PIXMAP) exaPixmapUseMemory ((PixmapPtr) pDstDrawable); - exaWaitSync (pDstDrawable->pScreen); - fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, - pbox, nbox, dx, dy, reverse, upsidedown, - bitplane, closure); + goto fallback; } /* If either drawable is already in framebuffer, try to get both of them @@ -664,15 +729,18 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, } (*pExaScr->info->accel.DoneCopy) (pDstPixmap); exaMarkSync(pDstDrawable->pScreen); + exaDrawableDirty (pDstDrawable); + return; } - else - { - exaWaitSync (pDstDrawable->pScreen); - fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, - pbox, nbox, dx, dy, reverse, upsidedown, - bitplane, closure); - } - exaDrawableDirty (pDstDrawable); + +fallback: + exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST); + exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC); + fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, + pbox, nbox, dx, dy, reverse, upsidedown, + bitplane, closure); + exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC); + exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST); } RegionPtr @@ -822,12 +890,12 @@ exaSolidBoxClipped (DrawablePtr pDrawable, !(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) || !(*pExaScr->info->accel.PrepareSolid) (pPixmap, GXcopy, pm, fg)) { - exaWaitSync (pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel); fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2, fbAnd (GXcopy, fg, pm), fbXor (GXcopy, fg, pm)); - exaDrawableDirty (pDrawable); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); return; } for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); @@ -949,8 +1017,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable, opaque = FALSE; } - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); ppci = ppciInit; while (nglyph--) @@ -996,6 +1063,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable, } x += pci->metrics.characterWidth; } + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } static const GCOps exaOps = { @@ -1121,14 +1189,15 @@ exaFillRegionSolid (DrawablePtr pDrawable, } (*pExaScr->info->accel.DoneSolid) (pPixmap); exaMarkSync(pDrawable->pScreen); + exaDrawableDirty (pDrawable); } else { - exaWaitSync (pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbFillRegionSolid (pDrawable, pRegion, 0, fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } - exaDrawableDirty (pDrawable); } static void diff --git a/exa/exa_migration.c b/exa/exa_migration.c index 29a94b31d..92ff394e2 100644 --- a/exa/exa_migration.c +++ b/exa/exa_migration.c @@ -78,6 +78,21 @@ exaGetPixmapPitch(PixmapPtr pPix) return pPix->devKind; } +/* Returns the size in bytes of the given pixmap in + * video memory. Only valid when the vram storage has been + * allocated + */ +unsigned long +exaGetPixmapSize(PixmapPtr pPix) +{ + ExaPixmapPrivPtr pExaPixmap; + + pExaPixmap = ExaGetPixmapPriv(pPix); + if (pExaPixmap != NULL) + return pExaPixmap->size; + return 0; +} + void exaDrawableDirty (DrawablePtr pDrawable) { @@ -185,6 +200,7 @@ exaPixmapAllocArea (PixmapPtr pPixmap) pitch = (w * bpp / 8) + (pExaScr->info->card.pixmapPitchAlign - 1); pitch -= pitch % pExaScr->info->card.pixmapPitchAlign; + pExaPixmap->size = pitch * h; pExaPixmap->devKind = pPixmap->devKind; pExaPixmap->devPrivate = pPixmap->devPrivate; pExaPixmap->area = exaOffscreenAlloc (pScreen, pitch * h, @@ -439,6 +455,7 @@ exaDrawableIsOffscreen (DrawablePtr pDrawable) { PixmapPtr pPixmap; STRACE; + if (pDrawable->type == DRAWABLE_WINDOW) pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); else @@ -446,6 +463,57 @@ exaDrawableIsOffscreen (DrawablePtr pDrawable) return exaPixmapIsOffscreen (pPixmap); } +void +exaPrepareAccess(DrawablePtr pDrawable, int index) +{ + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv (pScreen); + PixmapPtr pPixmap; + STRACE; + + if (pDrawable->type == DRAWABLE_WINDOW) + pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); + else + pPixmap = (PixmapPtr) pDrawable; + + if (index == EXA_PREPARE_DEST) + exaDrawableDirty (pDrawable); + if (exaPixmapIsOffscreen (pPixmap)) + exaWaitSync (pDrawable->pScreen); + else + return; + + if (pExaScr->info->accel.PrepareAccess == NULL) + return; + + if (!(*pExaScr->info->accel.PrepareAccess) (pPixmap, index)) { + ExaPixmapPriv (pPixmap); + assert (pExaPixmap->score != EXA_PIXMAP_SCORE_PINNED); + exaMoveOutPixmap (pPixmap); + } +} + +void +exaFinishAccess(DrawablePtr pDrawable, int index) +{ + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv (pScreen); + PixmapPtr pPixmap; + STRACE; + + if (pExaScr->info->accel.FinishAccess == NULL) + return; + + if (pDrawable->type == DRAWABLE_WINDOW) + pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); + else + pPixmap = (PixmapPtr) pDrawable; + if (!exaPixmapIsOffscreen (pPixmap)) + return; + + (*pExaScr->info->accel.FinishAccess) (pPixmap, index); +} + #if 0 static void exaFillTiled(int dst_x, @@ -620,10 +688,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, exaPixmapUseMemory ((PixmapPtr) pSrcDrawable); if (pDstDrawable->type == DRAWABLE_PIXMAP) exaPixmapUseMemory ((PixmapPtr) pDstDrawable); - exaWaitSync (pDstDrawable->pScreen); - fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, - pbox, nbox, dx, dy, reverse, upsidedown, - bitplane, closure); + goto fallback; } /* If either drawable is already in framebuffer, try to get both of them @@ -664,15 +729,18 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, } (*pExaScr->info->accel.DoneCopy) (pDstPixmap); exaMarkSync(pDstDrawable->pScreen); + exaDrawableDirty (pDstDrawable); + return; } - else - { - exaWaitSync (pDstDrawable->pScreen); - fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, - pbox, nbox, dx, dy, reverse, upsidedown, - bitplane, closure); - } - exaDrawableDirty (pDstDrawable); + +fallback: + exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST); + exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC); + fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, + pbox, nbox, dx, dy, reverse, upsidedown, + bitplane, closure); + exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC); + exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST); } RegionPtr @@ -822,12 +890,12 @@ exaSolidBoxClipped (DrawablePtr pDrawable, !(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) || !(*pExaScr->info->accel.PrepareSolid) (pPixmap, GXcopy, pm, fg)) { - exaWaitSync (pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel); fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2, fbAnd (GXcopy, fg, pm), fbXor (GXcopy, fg, pm)); - exaDrawableDirty (pDrawable); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); return; } for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); @@ -949,8 +1017,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable, opaque = FALSE; } - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); ppci = ppciInit; while (nglyph--) @@ -996,6 +1063,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable, } x += pci->metrics.characterWidth; } + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } static const GCOps exaOps = { @@ -1121,14 +1189,15 @@ exaFillRegionSolid (DrawablePtr pDrawable, } (*pExaScr->info->accel.DoneSolid) (pPixmap); exaMarkSync(pDrawable->pScreen); + exaDrawableDirty (pDrawable); } else { - exaWaitSync (pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbFillRegionSolid (pDrawable, pRegion, 0, fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } - exaDrawableDirty (pDrawable); } static void diff --git a/exa/exa_priv.h b/exa/exa_priv.h index 3d0904375..a53f370a3 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -103,6 +103,7 @@ typedef struct { int devKind; DevUnion devPrivate; Bool dirty; + unsigned int size; } ExaPixmapPrivRec, *ExaPixmapPrivPtr; @@ -246,6 +247,12 @@ exaPixmapUseScreen (PixmapPtr pPixmap); void exaPixmapUseMemory (PixmapPtr pPixmap); +void +exaPrepareAccess(DrawablePtr pDrawable, int index); + +void +exaFinishAccess(DrawablePtr pDrawable, int index); + void exaDrawableDirty(DrawablePtr pDrawable); diff --git a/exa/exa_render.c b/exa/exa_render.c index 5bfb07c4b..537f159e0 100644 --- a/exa/exa_render.c +++ b/exa/exa_render.c @@ -262,13 +262,8 @@ exaTryDriverSolidFill(PicturePtr pSrc, else pSrcPix = (PixmapPtr) (pSrc->pDrawable); - /* If source is offscreen, we need to sync the accelerator - * before accessing it. We'd prefer for it to be in memory. - */ - if (exaPixmapIsOffscreen(pSrcPix)) { - exaWaitSync(pDst->pDrawable->pScreen); - } + exaPrepareAccess(&pSrcPix->drawable, EXA_PREPARE_SRC); pixel = *(CARD32 *)(pSrcPix->devPrivate.ptr); if (!exaGetRGBAFromPixel(pixel, &red, &green, &blue, &alpha, pSrc->format)) @@ -276,6 +271,8 @@ exaTryDriverSolidFill(PicturePtr pSrc, REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return -1; } + exaFinishAccess(&pSrcPix->drawable, EXA_PREPARE_SRC); + exaGetPixelFromRGBA(&pixel, red, green, blue, alpha, pDst->format); diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c index c0927751b..93502c800 100644 --- a/exa/exa_unaccel.c +++ b/exa/exa_unaccel.c @@ -33,18 +33,18 @@ void ExaCheckFillSpans (DrawablePtr pDrawable, GCPtr pGC, int nspans, DDXPointPtr ppt, int *pwidth, int fSorted) { - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbFillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void ExaCheckSetSpans (DrawablePtr pDrawable, GCPtr pGC, char *psrc, DDXPointPtr ppt, int *pwidth, int nspans, int fSorted) { - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbSetSpans (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -52,18 +52,24 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *bits) { - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } RegionPtr ExaCheckCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty) { - exaWaitSync (pSrc->pScreen); - exaDrawableDirty (pDst); - return fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); + RegionPtr ret; + + exaPrepareAccess (pDst, EXA_PREPARE_DEST); + exaPrepareAccess (pSrc, EXA_PREPARE_SRC); + ret = fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); + exaFinishAccess (pSrc, EXA_PREPARE_SRC); + exaFinishAccess (pDst, EXA_PREPARE_DEST); + + return ret; } RegionPtr @@ -71,19 +77,25 @@ ExaCheckCopyPlane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long bitPlane) { - exaWaitSync (pSrc->pScreen); - exaDrawableDirty (pDst); - return fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, - bitPlane); + RegionPtr ret; + + exaPrepareAccess (pDst, EXA_PREPARE_DEST); + exaPrepareAccess (pSrc, EXA_PREPARE_SRC); + ret = fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, + bitPlane); + exaFinishAccess (pSrc, EXA_PREPARE_SRC); + exaFinishAccess (pDst, EXA_PREPARE_DEST); + + return ret; } void ExaCheckPolyPoint (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr pptInit) { - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPolyPoint (pDrawable, pGC, mode, npt, pptInit); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -92,10 +104,11 @@ ExaCheckPolylines (DrawablePtr pDrawable, GCPtr pGC, { if (pGC->lineWidth == 0) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbPolyLine (pDrawable, pGC, mode, npt, ppt); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + return; } - exaDrawableDirty (pDrawable); fbPolyLine (pDrawable, pGC, mode, npt, ppt); } @@ -104,10 +117,11 @@ ExaCheckPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nsegInit, xSegment *pSegInit) { if (pGC->lineWidth == 0) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbPolySegment (pDrawable, pGC, nsegInit, pSegInit); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + return; } - exaDrawableDirty (pDrawable); fbPolySegment (pDrawable, pGC, nsegInit, pSegInit); } @@ -116,8 +130,10 @@ ExaCheckPolyRectangle (DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle *prect) { if (pGC->lineWidth == 0) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbPolyRectangle (pDrawable, pGC, nrects, prect); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + return; } fbPolyRectangle (pDrawable, pGC, nrects, prect); } @@ -128,12 +144,12 @@ ExaCheckPolyArc (DrawablePtr pDrawable, GCPtr pGC, { if (pGC->lineWidth == 0) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPolyArc (pDrawable, pGC, narcs, pArcs); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + return; } - else - miPolyArc (pDrawable, pGC, narcs, pArcs); + miPolyArc (pDrawable, pGC, narcs, pArcs); } #if 0 @@ -141,9 +157,9 @@ void ExaCheckFillPolygon (DrawablePtr pDrawable, GCPtr pGC, int shape, int mode, int count, DDXPointPtr pPts) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbFillPolygon (pDrawable, pGC, mode, count, pPts); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } #endif @@ -151,18 +167,18 @@ void ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPolyFillRect (pDrawable, pGC, nrect, prect); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void ExaCheckPolyFillArc (DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *pArcs) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPolyFillArc (pDrawable, pGC, narcs, pArcs); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -170,9 +186,9 @@ ExaCheckImageGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -180,9 +196,9 @@ ExaCheckPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -190,9 +206,9 @@ ExaCheckPushPixels (GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable, int w, int h, int x, int y) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPushPixels (pGC, pBitmap, pDrawable, w, h, x, y); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -201,8 +217,9 @@ ExaCheckGetImage (DrawablePtr pDrawable, unsigned int format, unsigned long planeMask, char *d) { - exaWaitSync(pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_SRC); fbGetImage (pDrawable, x, y, w, h, format, planeMask, d); + exaFinishAccess (pDrawable, EXA_PREPARE_SRC); } void @@ -213,8 +230,9 @@ ExaCheckGetSpans (DrawablePtr pDrawable, int nspans, char *pdstStart) { - exaWaitSync(pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_SRC); fbGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + exaFinishAccess (pDrawable, EXA_PREPARE_SRC); } void @@ -224,9 +242,9 @@ ExaCheckSaveAreas (PixmapPtr pPixmap, int yorg, WindowPtr pWin) { - exaWaitSync(pWin->drawable.pScreen); - exaDrawableDirty (&pPixmap->drawable); + exaPrepareAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST); fbSaveAreas (pPixmap, prgnSave, xorg, yorg, pWin); + exaFinishAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST); } void @@ -236,17 +254,17 @@ ExaCheckRestoreAreas (PixmapPtr pPixmap, int yorg, WindowPtr pWin) { - exaWaitSync(pWin->drawable.pScreen); - exaDrawableDirty ((DrawablePtr)pWin); + exaPrepareAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST); fbRestoreAreas (pPixmap, prgnSave, xorg, yorg, pWin); + exaFinishAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST); } void ExaCheckPaintWindow (WindowPtr pWin, RegionPtr pRegion, int what) { - exaWaitSync (pWin->drawable.pScreen); - exaDrawableDirty ((DrawablePtr)pWin); + exaPrepareAccess (&pWin->drawable, EXA_PREPARE_DEST); fbPaintWindow (pWin, pRegion, what); + exaFinishAccess (&pWin->drawable, EXA_PREPARE_DEST); } void @@ -263,8 +281,10 @@ ExaCheckComposite (CARD8 op, CARD16 width, CARD16 height) { - exaWaitSync (pDst->pDrawable->pScreen); - exaDrawableDirty (pDst->pDrawable); + exaPrepareAccess (pDst->pDrawable, EXA_PREPARE_DEST); + exaPrepareAccess (pSrc->pDrawable, EXA_PREPARE_SRC); + if (pMask) + exaPrepareAccess (pMask->pDrawable, EXA_PREPARE_MASK); fbComposite (op, pSrc, pMask, @@ -277,6 +297,10 @@ ExaCheckComposite (CARD8 op, yDst, width, height); + if (pMask) + exaFinishAccess (pMask->pDrawable, EXA_PREPARE_MASK); + exaFinishAccess (pSrc->pDrawable, EXA_PREPARE_SRC); + exaFinishAccess (pDst->pDrawable, EXA_PREPARE_DEST); } /* diff --git a/hw/xfree86/exa/exa.c b/hw/xfree86/exa/exa.c index 29a94b31d..92ff394e2 100644 --- a/hw/xfree86/exa/exa.c +++ b/hw/xfree86/exa/exa.c @@ -78,6 +78,21 @@ exaGetPixmapPitch(PixmapPtr pPix) return pPix->devKind; } +/* Returns the size in bytes of the given pixmap in + * video memory. Only valid when the vram storage has been + * allocated + */ +unsigned long +exaGetPixmapSize(PixmapPtr pPix) +{ + ExaPixmapPrivPtr pExaPixmap; + + pExaPixmap = ExaGetPixmapPriv(pPix); + if (pExaPixmap != NULL) + return pExaPixmap->size; + return 0; +} + void exaDrawableDirty (DrawablePtr pDrawable) { @@ -185,6 +200,7 @@ exaPixmapAllocArea (PixmapPtr pPixmap) pitch = (w * bpp / 8) + (pExaScr->info->card.pixmapPitchAlign - 1); pitch -= pitch % pExaScr->info->card.pixmapPitchAlign; + pExaPixmap->size = pitch * h; pExaPixmap->devKind = pPixmap->devKind; pExaPixmap->devPrivate = pPixmap->devPrivate; pExaPixmap->area = exaOffscreenAlloc (pScreen, pitch * h, @@ -439,6 +455,7 @@ exaDrawableIsOffscreen (DrawablePtr pDrawable) { PixmapPtr pPixmap; STRACE; + if (pDrawable->type == DRAWABLE_WINDOW) pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); else @@ -446,6 +463,57 @@ exaDrawableIsOffscreen (DrawablePtr pDrawable) return exaPixmapIsOffscreen (pPixmap); } +void +exaPrepareAccess(DrawablePtr pDrawable, int index) +{ + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv (pScreen); + PixmapPtr pPixmap; + STRACE; + + if (pDrawable->type == DRAWABLE_WINDOW) + pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); + else + pPixmap = (PixmapPtr) pDrawable; + + if (index == EXA_PREPARE_DEST) + exaDrawableDirty (pDrawable); + if (exaPixmapIsOffscreen (pPixmap)) + exaWaitSync (pDrawable->pScreen); + else + return; + + if (pExaScr->info->accel.PrepareAccess == NULL) + return; + + if (!(*pExaScr->info->accel.PrepareAccess) (pPixmap, index)) { + ExaPixmapPriv (pPixmap); + assert (pExaPixmap->score != EXA_PIXMAP_SCORE_PINNED); + exaMoveOutPixmap (pPixmap); + } +} + +void +exaFinishAccess(DrawablePtr pDrawable, int index) +{ + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv (pScreen); + PixmapPtr pPixmap; + STRACE; + + if (pExaScr->info->accel.FinishAccess == NULL) + return; + + if (pDrawable->type == DRAWABLE_WINDOW) + pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); + else + pPixmap = (PixmapPtr) pDrawable; + if (!exaPixmapIsOffscreen (pPixmap)) + return; + + (*pExaScr->info->accel.FinishAccess) (pPixmap, index); +} + #if 0 static void exaFillTiled(int dst_x, @@ -620,10 +688,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, exaPixmapUseMemory ((PixmapPtr) pSrcDrawable); if (pDstDrawable->type == DRAWABLE_PIXMAP) exaPixmapUseMemory ((PixmapPtr) pDstDrawable); - exaWaitSync (pDstDrawable->pScreen); - fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, - pbox, nbox, dx, dy, reverse, upsidedown, - bitplane, closure); + goto fallback; } /* If either drawable is already in framebuffer, try to get both of them @@ -664,15 +729,18 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, } (*pExaScr->info->accel.DoneCopy) (pDstPixmap); exaMarkSync(pDstDrawable->pScreen); + exaDrawableDirty (pDstDrawable); + return; } - else - { - exaWaitSync (pDstDrawable->pScreen); - fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, - pbox, nbox, dx, dy, reverse, upsidedown, - bitplane, closure); - } - exaDrawableDirty (pDstDrawable); + +fallback: + exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST); + exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC); + fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, + pbox, nbox, dx, dy, reverse, upsidedown, + bitplane, closure); + exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC); + exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST); } RegionPtr @@ -822,12 +890,12 @@ exaSolidBoxClipped (DrawablePtr pDrawable, !(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) || !(*pExaScr->info->accel.PrepareSolid) (pPixmap, GXcopy, pm, fg)) { - exaWaitSync (pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel); fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2, fbAnd (GXcopy, fg, pm), fbXor (GXcopy, fg, pm)); - exaDrawableDirty (pDrawable); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); return; } for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); @@ -949,8 +1017,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable, opaque = FALSE; } - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); ppci = ppciInit; while (nglyph--) @@ -996,6 +1063,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable, } x += pci->metrics.characterWidth; } + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } static const GCOps exaOps = { @@ -1121,14 +1189,15 @@ exaFillRegionSolid (DrawablePtr pDrawable, } (*pExaScr->info->accel.DoneSolid) (pPixmap); exaMarkSync(pDrawable->pScreen); + exaDrawableDirty (pDrawable); } else { - exaWaitSync (pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbFillRegionSolid (pDrawable, pRegion, 0, fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } - exaDrawableDirty (pDrawable); } static void diff --git a/hw/xfree86/exa/exa.h b/hw/xfree86/exa/exa.h index 2cf9fe44a..5e850a3cf 100644 --- a/hw/xfree86/exa/exa.h +++ b/hw/xfree86/exa/exa.h @@ -175,6 +175,24 @@ typedef struct _ExaAccelInfo { */ int (*MarkSync) (ScreenPtr pScreen); void (*WaitMarker) (ScreenPtr pScreen, int marker); + + /* These are wrapping all fb or composite operations that will cause + * a direct access to the framebuffer. You can use them to update + * endian swappers, force migration to RAM, or whatever else you find + * useful at this point. EXA can stack up to 3 calls to Prepare/Finish + * access, though they will have a different index. If your hardware + * doesn't have enough separate configurable swapper, you can return + * FALSE from PrepareAccess() to force EXA to migrate the pixmap to RAM. + * Note that DownloadFromScreen and UploadToScreen can both be called + * between PrepareAccess() and FinishAccess(). If they need to use a + * swapper, they should save & restore its setting. + */ + Bool (*PrepareAccess)(PixmapPtr pPix, int index); + void (*FinishAccess)(PixmapPtr pPix, int index); + #define EXA_PREPARE_DEST 0 + #define EXA_PREPARE_SRC 1 + #define EXA_PREPARE_MASK 2 + } ExaAccelInfoRec, *ExaAccelInfoPtr; typedef struct _ExaDriver { @@ -224,6 +242,9 @@ exaGetPixmapOffset(PixmapPtr pPix); unsigned long exaGetPixmapPitch(PixmapPtr pPix); +unsigned long +exaGetPixmapSize(PixmapPtr pPix); + #define exaInitCard(exa, sync, memory_base, off_screen_base, memory_size, \ offscreen_byte_align, offscreen_pitch, flags, \ max_x, max_y) \ diff --git a/hw/xfree86/exa/exaPriv.h b/hw/xfree86/exa/exaPriv.h index 3d0904375..a53f370a3 100644 --- a/hw/xfree86/exa/exaPriv.h +++ b/hw/xfree86/exa/exaPriv.h @@ -103,6 +103,7 @@ typedef struct { int devKind; DevUnion devPrivate; Bool dirty; + unsigned int size; } ExaPixmapPrivRec, *ExaPixmapPrivPtr; @@ -246,6 +247,12 @@ exaPixmapUseScreen (PixmapPtr pPixmap); void exaPixmapUseMemory (PixmapPtr pPixmap); +void +exaPrepareAccess(DrawablePtr pDrawable, int index); + +void +exaFinishAccess(DrawablePtr pDrawable, int index); + void exaDrawableDirty(DrawablePtr pDrawable); diff --git a/hw/xfree86/exa/exa_accel.c b/hw/xfree86/exa/exa_accel.c index 29a94b31d..92ff394e2 100644 --- a/hw/xfree86/exa/exa_accel.c +++ b/hw/xfree86/exa/exa_accel.c @@ -78,6 +78,21 @@ exaGetPixmapPitch(PixmapPtr pPix) return pPix->devKind; } +/* Returns the size in bytes of the given pixmap in + * video memory. Only valid when the vram storage has been + * allocated + */ +unsigned long +exaGetPixmapSize(PixmapPtr pPix) +{ + ExaPixmapPrivPtr pExaPixmap; + + pExaPixmap = ExaGetPixmapPriv(pPix); + if (pExaPixmap != NULL) + return pExaPixmap->size; + return 0; +} + void exaDrawableDirty (DrawablePtr pDrawable) { @@ -185,6 +200,7 @@ exaPixmapAllocArea (PixmapPtr pPixmap) pitch = (w * bpp / 8) + (pExaScr->info->card.pixmapPitchAlign - 1); pitch -= pitch % pExaScr->info->card.pixmapPitchAlign; + pExaPixmap->size = pitch * h; pExaPixmap->devKind = pPixmap->devKind; pExaPixmap->devPrivate = pPixmap->devPrivate; pExaPixmap->area = exaOffscreenAlloc (pScreen, pitch * h, @@ -439,6 +455,7 @@ exaDrawableIsOffscreen (DrawablePtr pDrawable) { PixmapPtr pPixmap; STRACE; + if (pDrawable->type == DRAWABLE_WINDOW) pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); else @@ -446,6 +463,57 @@ exaDrawableIsOffscreen (DrawablePtr pDrawable) return exaPixmapIsOffscreen (pPixmap); } +void +exaPrepareAccess(DrawablePtr pDrawable, int index) +{ + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv (pScreen); + PixmapPtr pPixmap; + STRACE; + + if (pDrawable->type == DRAWABLE_WINDOW) + pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); + else + pPixmap = (PixmapPtr) pDrawable; + + if (index == EXA_PREPARE_DEST) + exaDrawableDirty (pDrawable); + if (exaPixmapIsOffscreen (pPixmap)) + exaWaitSync (pDrawable->pScreen); + else + return; + + if (pExaScr->info->accel.PrepareAccess == NULL) + return; + + if (!(*pExaScr->info->accel.PrepareAccess) (pPixmap, index)) { + ExaPixmapPriv (pPixmap); + assert (pExaPixmap->score != EXA_PIXMAP_SCORE_PINNED); + exaMoveOutPixmap (pPixmap); + } +} + +void +exaFinishAccess(DrawablePtr pDrawable, int index) +{ + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv (pScreen); + PixmapPtr pPixmap; + STRACE; + + if (pExaScr->info->accel.FinishAccess == NULL) + return; + + if (pDrawable->type == DRAWABLE_WINDOW) + pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); + else + pPixmap = (PixmapPtr) pDrawable; + if (!exaPixmapIsOffscreen (pPixmap)) + return; + + (*pExaScr->info->accel.FinishAccess) (pPixmap, index); +} + #if 0 static void exaFillTiled(int dst_x, @@ -620,10 +688,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, exaPixmapUseMemory ((PixmapPtr) pSrcDrawable); if (pDstDrawable->type == DRAWABLE_PIXMAP) exaPixmapUseMemory ((PixmapPtr) pDstDrawable); - exaWaitSync (pDstDrawable->pScreen); - fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, - pbox, nbox, dx, dy, reverse, upsidedown, - bitplane, closure); + goto fallback; } /* If either drawable is already in framebuffer, try to get both of them @@ -664,15 +729,18 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, } (*pExaScr->info->accel.DoneCopy) (pDstPixmap); exaMarkSync(pDstDrawable->pScreen); + exaDrawableDirty (pDstDrawable); + return; } - else - { - exaWaitSync (pDstDrawable->pScreen); - fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, - pbox, nbox, dx, dy, reverse, upsidedown, - bitplane, closure); - } - exaDrawableDirty (pDstDrawable); + +fallback: + exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST); + exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC); + fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, + pbox, nbox, dx, dy, reverse, upsidedown, + bitplane, closure); + exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC); + exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST); } RegionPtr @@ -822,12 +890,12 @@ exaSolidBoxClipped (DrawablePtr pDrawable, !(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) || !(*pExaScr->info->accel.PrepareSolid) (pPixmap, GXcopy, pm, fg)) { - exaWaitSync (pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel); fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2, fbAnd (GXcopy, fg, pm), fbXor (GXcopy, fg, pm)); - exaDrawableDirty (pDrawable); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); return; } for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); @@ -949,8 +1017,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable, opaque = FALSE; } - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); ppci = ppciInit; while (nglyph--) @@ -996,6 +1063,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable, } x += pci->metrics.characterWidth; } + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } static const GCOps exaOps = { @@ -1121,14 +1189,15 @@ exaFillRegionSolid (DrawablePtr pDrawable, } (*pExaScr->info->accel.DoneSolid) (pPixmap); exaMarkSync(pDrawable->pScreen); + exaDrawableDirty (pDrawable); } else { - exaWaitSync (pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbFillRegionSolid (pDrawable, pRegion, 0, fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } - exaDrawableDirty (pDrawable); } static void diff --git a/hw/xfree86/exa/exa_migration.c b/hw/xfree86/exa/exa_migration.c index 29a94b31d..92ff394e2 100644 --- a/hw/xfree86/exa/exa_migration.c +++ b/hw/xfree86/exa/exa_migration.c @@ -78,6 +78,21 @@ exaGetPixmapPitch(PixmapPtr pPix) return pPix->devKind; } +/* Returns the size in bytes of the given pixmap in + * video memory. Only valid when the vram storage has been + * allocated + */ +unsigned long +exaGetPixmapSize(PixmapPtr pPix) +{ + ExaPixmapPrivPtr pExaPixmap; + + pExaPixmap = ExaGetPixmapPriv(pPix); + if (pExaPixmap != NULL) + return pExaPixmap->size; + return 0; +} + void exaDrawableDirty (DrawablePtr pDrawable) { @@ -185,6 +200,7 @@ exaPixmapAllocArea (PixmapPtr pPixmap) pitch = (w * bpp / 8) + (pExaScr->info->card.pixmapPitchAlign - 1); pitch -= pitch % pExaScr->info->card.pixmapPitchAlign; + pExaPixmap->size = pitch * h; pExaPixmap->devKind = pPixmap->devKind; pExaPixmap->devPrivate = pPixmap->devPrivate; pExaPixmap->area = exaOffscreenAlloc (pScreen, pitch * h, @@ -439,6 +455,7 @@ exaDrawableIsOffscreen (DrawablePtr pDrawable) { PixmapPtr pPixmap; STRACE; + if (pDrawable->type == DRAWABLE_WINDOW) pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); else @@ -446,6 +463,57 @@ exaDrawableIsOffscreen (DrawablePtr pDrawable) return exaPixmapIsOffscreen (pPixmap); } +void +exaPrepareAccess(DrawablePtr pDrawable, int index) +{ + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv (pScreen); + PixmapPtr pPixmap; + STRACE; + + if (pDrawable->type == DRAWABLE_WINDOW) + pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); + else + pPixmap = (PixmapPtr) pDrawable; + + if (index == EXA_PREPARE_DEST) + exaDrawableDirty (pDrawable); + if (exaPixmapIsOffscreen (pPixmap)) + exaWaitSync (pDrawable->pScreen); + else + return; + + if (pExaScr->info->accel.PrepareAccess == NULL) + return; + + if (!(*pExaScr->info->accel.PrepareAccess) (pPixmap, index)) { + ExaPixmapPriv (pPixmap); + assert (pExaPixmap->score != EXA_PIXMAP_SCORE_PINNED); + exaMoveOutPixmap (pPixmap); + } +} + +void +exaFinishAccess(DrawablePtr pDrawable, int index) +{ + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv (pScreen); + PixmapPtr pPixmap; + STRACE; + + if (pExaScr->info->accel.FinishAccess == NULL) + return; + + if (pDrawable->type == DRAWABLE_WINDOW) + pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); + else + pPixmap = (PixmapPtr) pDrawable; + if (!exaPixmapIsOffscreen (pPixmap)) + return; + + (*pExaScr->info->accel.FinishAccess) (pPixmap, index); +} + #if 0 static void exaFillTiled(int dst_x, @@ -620,10 +688,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, exaPixmapUseMemory ((PixmapPtr) pSrcDrawable); if (pDstDrawable->type == DRAWABLE_PIXMAP) exaPixmapUseMemory ((PixmapPtr) pDstDrawable); - exaWaitSync (pDstDrawable->pScreen); - fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, - pbox, nbox, dx, dy, reverse, upsidedown, - bitplane, closure); + goto fallback; } /* If either drawable is already in framebuffer, try to get both of them @@ -664,15 +729,18 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, } (*pExaScr->info->accel.DoneCopy) (pDstPixmap); exaMarkSync(pDstDrawable->pScreen); + exaDrawableDirty (pDstDrawable); + return; } - else - { - exaWaitSync (pDstDrawable->pScreen); - fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, - pbox, nbox, dx, dy, reverse, upsidedown, - bitplane, closure); - } - exaDrawableDirty (pDstDrawable); + +fallback: + exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST); + exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC); + fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, + pbox, nbox, dx, dy, reverse, upsidedown, + bitplane, closure); + exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC); + exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST); } RegionPtr @@ -822,12 +890,12 @@ exaSolidBoxClipped (DrawablePtr pDrawable, !(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) || !(*pExaScr->info->accel.PrepareSolid) (pPixmap, GXcopy, pm, fg)) { - exaWaitSync (pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel); fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2, fbAnd (GXcopy, fg, pm), fbXor (GXcopy, fg, pm)); - exaDrawableDirty (pDrawable); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); return; } for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); @@ -949,8 +1017,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable, opaque = FALSE; } - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); ppci = ppciInit; while (nglyph--) @@ -996,6 +1063,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable, } x += pci->metrics.characterWidth; } + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } static const GCOps exaOps = { @@ -1121,14 +1189,15 @@ exaFillRegionSolid (DrawablePtr pDrawable, } (*pExaScr->info->accel.DoneSolid) (pPixmap); exaMarkSync(pDrawable->pScreen); + exaDrawableDirty (pDrawable); } else { - exaWaitSync (pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbFillRegionSolid (pDrawable, pRegion, 0, fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } - exaDrawableDirty (pDrawable); } static void diff --git a/hw/xfree86/exa/exa_priv.h b/hw/xfree86/exa/exa_priv.h index 3d0904375..a53f370a3 100644 --- a/hw/xfree86/exa/exa_priv.h +++ b/hw/xfree86/exa/exa_priv.h @@ -103,6 +103,7 @@ typedef struct { int devKind; DevUnion devPrivate; Bool dirty; + unsigned int size; } ExaPixmapPrivRec, *ExaPixmapPrivPtr; @@ -246,6 +247,12 @@ exaPixmapUseScreen (PixmapPtr pPixmap); void exaPixmapUseMemory (PixmapPtr pPixmap); +void +exaPrepareAccess(DrawablePtr pDrawable, int index); + +void +exaFinishAccess(DrawablePtr pDrawable, int index); + void exaDrawableDirty(DrawablePtr pDrawable); diff --git a/hw/xfree86/exa/exa_render.c b/hw/xfree86/exa/exa_render.c index 5bfb07c4b..537f159e0 100644 --- a/hw/xfree86/exa/exa_render.c +++ b/hw/xfree86/exa/exa_render.c @@ -262,13 +262,8 @@ exaTryDriverSolidFill(PicturePtr pSrc, else pSrcPix = (PixmapPtr) (pSrc->pDrawable); - /* If source is offscreen, we need to sync the accelerator - * before accessing it. We'd prefer for it to be in memory. - */ - if (exaPixmapIsOffscreen(pSrcPix)) { - exaWaitSync(pDst->pDrawable->pScreen); - } + exaPrepareAccess(&pSrcPix->drawable, EXA_PREPARE_SRC); pixel = *(CARD32 *)(pSrcPix->devPrivate.ptr); if (!exaGetRGBAFromPixel(pixel, &red, &green, &blue, &alpha, pSrc->format)) @@ -276,6 +271,8 @@ exaTryDriverSolidFill(PicturePtr pSrc, REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return -1; } + exaFinishAccess(&pSrcPix->drawable, EXA_PREPARE_SRC); + exaGetPixelFromRGBA(&pixel, red, green, blue, alpha, pDst->format); diff --git a/hw/xfree86/exa/exa_unaccel.c b/hw/xfree86/exa/exa_unaccel.c index c0927751b..93502c800 100644 --- a/hw/xfree86/exa/exa_unaccel.c +++ b/hw/xfree86/exa/exa_unaccel.c @@ -33,18 +33,18 @@ void ExaCheckFillSpans (DrawablePtr pDrawable, GCPtr pGC, int nspans, DDXPointPtr ppt, int *pwidth, int fSorted) { - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbFillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void ExaCheckSetSpans (DrawablePtr pDrawable, GCPtr pGC, char *psrc, DDXPointPtr ppt, int *pwidth, int nspans, int fSorted) { - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbSetSpans (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -52,18 +52,24 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *bits) { - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } RegionPtr ExaCheckCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty) { - exaWaitSync (pSrc->pScreen); - exaDrawableDirty (pDst); - return fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); + RegionPtr ret; + + exaPrepareAccess (pDst, EXA_PREPARE_DEST); + exaPrepareAccess (pSrc, EXA_PREPARE_SRC); + ret = fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); + exaFinishAccess (pSrc, EXA_PREPARE_SRC); + exaFinishAccess (pDst, EXA_PREPARE_DEST); + + return ret; } RegionPtr @@ -71,19 +77,25 @@ ExaCheckCopyPlane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long bitPlane) { - exaWaitSync (pSrc->pScreen); - exaDrawableDirty (pDst); - return fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, - bitPlane); + RegionPtr ret; + + exaPrepareAccess (pDst, EXA_PREPARE_DEST); + exaPrepareAccess (pSrc, EXA_PREPARE_SRC); + ret = fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, + bitPlane); + exaFinishAccess (pSrc, EXA_PREPARE_SRC); + exaFinishAccess (pDst, EXA_PREPARE_DEST); + + return ret; } void ExaCheckPolyPoint (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr pptInit) { - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPolyPoint (pDrawable, pGC, mode, npt, pptInit); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -92,10 +104,11 @@ ExaCheckPolylines (DrawablePtr pDrawable, GCPtr pGC, { if (pGC->lineWidth == 0) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbPolyLine (pDrawable, pGC, mode, npt, ppt); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + return; } - exaDrawableDirty (pDrawable); fbPolyLine (pDrawable, pGC, mode, npt, ppt); } @@ -104,10 +117,11 @@ ExaCheckPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nsegInit, xSegment *pSegInit) { if (pGC->lineWidth == 0) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbPolySegment (pDrawable, pGC, nsegInit, pSegInit); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + return; } - exaDrawableDirty (pDrawable); fbPolySegment (pDrawable, pGC, nsegInit, pSegInit); } @@ -116,8 +130,10 @@ ExaCheckPolyRectangle (DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle *prect) { if (pGC->lineWidth == 0) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbPolyRectangle (pDrawable, pGC, nrects, prect); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + return; } fbPolyRectangle (pDrawable, pGC, nrects, prect); } @@ -128,12 +144,12 @@ ExaCheckPolyArc (DrawablePtr pDrawable, GCPtr pGC, { if (pGC->lineWidth == 0) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPolyArc (pDrawable, pGC, narcs, pArcs); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + return; } - else - miPolyArc (pDrawable, pGC, narcs, pArcs); + miPolyArc (pDrawable, pGC, narcs, pArcs); } #if 0 @@ -141,9 +157,9 @@ void ExaCheckFillPolygon (DrawablePtr pDrawable, GCPtr pGC, int shape, int mode, int count, DDXPointPtr pPts) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbFillPolygon (pDrawable, pGC, mode, count, pPts); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } #endif @@ -151,18 +167,18 @@ void ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPolyFillRect (pDrawable, pGC, nrect, prect); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void ExaCheckPolyFillArc (DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *pArcs) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPolyFillArc (pDrawable, pGC, narcs, pArcs); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -170,9 +186,9 @@ ExaCheckImageGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -180,9 +196,9 @@ ExaCheckPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -190,9 +206,9 @@ ExaCheckPushPixels (GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable, int w, int h, int x, int y) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPushPixels (pGC, pBitmap, pDrawable, w, h, x, y); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -201,8 +217,9 @@ ExaCheckGetImage (DrawablePtr pDrawable, unsigned int format, unsigned long planeMask, char *d) { - exaWaitSync(pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_SRC); fbGetImage (pDrawable, x, y, w, h, format, planeMask, d); + exaFinishAccess (pDrawable, EXA_PREPARE_SRC); } void @@ -213,8 +230,9 @@ ExaCheckGetSpans (DrawablePtr pDrawable, int nspans, char *pdstStart) { - exaWaitSync(pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_SRC); fbGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + exaFinishAccess (pDrawable, EXA_PREPARE_SRC); } void @@ -224,9 +242,9 @@ ExaCheckSaveAreas (PixmapPtr pPixmap, int yorg, WindowPtr pWin) { - exaWaitSync(pWin->drawable.pScreen); - exaDrawableDirty (&pPixmap->drawable); + exaPrepareAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST); fbSaveAreas (pPixmap, prgnSave, xorg, yorg, pWin); + exaFinishAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST); } void @@ -236,17 +254,17 @@ ExaCheckRestoreAreas (PixmapPtr pPixmap, int yorg, WindowPtr pWin) { - exaWaitSync(pWin->drawable.pScreen); - exaDrawableDirty ((DrawablePtr)pWin); + exaPrepareAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST); fbRestoreAreas (pPixmap, prgnSave, xorg, yorg, pWin); + exaFinishAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST); } void ExaCheckPaintWindow (WindowPtr pWin, RegionPtr pRegion, int what) { - exaWaitSync (pWin->drawable.pScreen); - exaDrawableDirty ((DrawablePtr)pWin); + exaPrepareAccess (&pWin->drawable, EXA_PREPARE_DEST); fbPaintWindow (pWin, pRegion, what); + exaFinishAccess (&pWin->drawable, EXA_PREPARE_DEST); } void @@ -263,8 +281,10 @@ ExaCheckComposite (CARD8 op, CARD16 width, CARD16 height) { - exaWaitSync (pDst->pDrawable->pScreen); - exaDrawableDirty (pDst->pDrawable); + exaPrepareAccess (pDst->pDrawable, EXA_PREPARE_DEST); + exaPrepareAccess (pSrc->pDrawable, EXA_PREPARE_SRC); + if (pMask) + exaPrepareAccess (pMask->pDrawable, EXA_PREPARE_MASK); fbComposite (op, pSrc, pMask, @@ -277,6 +297,10 @@ ExaCheckComposite (CARD8 op, yDst, width, height); + if (pMask) + exaFinishAccess (pMask->pDrawable, EXA_PREPARE_MASK); + exaFinishAccess (pSrc->pDrawable, EXA_PREPARE_SRC); + exaFinishAccess (pDst->pDrawable, EXA_PREPARE_DEST); } /* diff --git a/hw/xfree86/exa/exaasync.c b/hw/xfree86/exa/exaasync.c index c0927751b..93502c800 100644 --- a/hw/xfree86/exa/exaasync.c +++ b/hw/xfree86/exa/exaasync.c @@ -33,18 +33,18 @@ void ExaCheckFillSpans (DrawablePtr pDrawable, GCPtr pGC, int nspans, DDXPointPtr ppt, int *pwidth, int fSorted) { - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbFillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void ExaCheckSetSpans (DrawablePtr pDrawable, GCPtr pGC, char *psrc, DDXPointPtr ppt, int *pwidth, int nspans, int fSorted) { - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbSetSpans (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -52,18 +52,24 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *bits) { - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } RegionPtr ExaCheckCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty) { - exaWaitSync (pSrc->pScreen); - exaDrawableDirty (pDst); - return fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); + RegionPtr ret; + + exaPrepareAccess (pDst, EXA_PREPARE_DEST); + exaPrepareAccess (pSrc, EXA_PREPARE_SRC); + ret = fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); + exaFinishAccess (pSrc, EXA_PREPARE_SRC); + exaFinishAccess (pDst, EXA_PREPARE_DEST); + + return ret; } RegionPtr @@ -71,19 +77,25 @@ ExaCheckCopyPlane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long bitPlane) { - exaWaitSync (pSrc->pScreen); - exaDrawableDirty (pDst); - return fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, - bitPlane); + RegionPtr ret; + + exaPrepareAccess (pDst, EXA_PREPARE_DEST); + exaPrepareAccess (pSrc, EXA_PREPARE_SRC); + ret = fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, + bitPlane); + exaFinishAccess (pSrc, EXA_PREPARE_SRC); + exaFinishAccess (pDst, EXA_PREPARE_DEST); + + return ret; } void ExaCheckPolyPoint (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr pptInit) { - exaWaitSync (pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPolyPoint (pDrawable, pGC, mode, npt, pptInit); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -92,10 +104,11 @@ ExaCheckPolylines (DrawablePtr pDrawable, GCPtr pGC, { if (pGC->lineWidth == 0) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbPolyLine (pDrawable, pGC, mode, npt, ppt); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + return; } - exaDrawableDirty (pDrawable); fbPolyLine (pDrawable, pGC, mode, npt, ppt); } @@ -104,10 +117,11 @@ ExaCheckPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nsegInit, xSegment *pSegInit) { if (pGC->lineWidth == 0) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbPolySegment (pDrawable, pGC, nsegInit, pSegInit); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + return; } - exaDrawableDirty (pDrawable); fbPolySegment (pDrawable, pGC, nsegInit, pSegInit); } @@ -116,8 +130,10 @@ ExaCheckPolyRectangle (DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle *prect) { if (pGC->lineWidth == 0) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbPolyRectangle (pDrawable, pGC, nrects, prect); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + return; } fbPolyRectangle (pDrawable, pGC, nrects, prect); } @@ -128,12 +144,12 @@ ExaCheckPolyArc (DrawablePtr pDrawable, GCPtr pGC, { if (pGC->lineWidth == 0) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPolyArc (pDrawable, pGC, narcs, pArcs); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + return; } - else - miPolyArc (pDrawable, pGC, narcs, pArcs); + miPolyArc (pDrawable, pGC, narcs, pArcs); } #if 0 @@ -141,9 +157,9 @@ void ExaCheckFillPolygon (DrawablePtr pDrawable, GCPtr pGC, int shape, int mode, int count, DDXPointPtr pPts) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbFillPolygon (pDrawable, pGC, mode, count, pPts); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } #endif @@ -151,18 +167,18 @@ void ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPolyFillRect (pDrawable, pGC, nrect, prect); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void ExaCheckPolyFillArc (DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *pArcs) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPolyFillArc (pDrawable, pGC, narcs, pArcs); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -170,9 +186,9 @@ ExaCheckImageGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -180,9 +196,9 @@ ExaCheckPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -190,9 +206,9 @@ ExaCheckPushPixels (GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable, int w, int h, int x, int y) { - exaWaitSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPushPixels (pGC, pBitmap, pDrawable, w, h, x, y); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void @@ -201,8 +217,9 @@ ExaCheckGetImage (DrawablePtr pDrawable, unsigned int format, unsigned long planeMask, char *d) { - exaWaitSync(pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_SRC); fbGetImage (pDrawable, x, y, w, h, format, planeMask, d); + exaFinishAccess (pDrawable, EXA_PREPARE_SRC); } void @@ -213,8 +230,9 @@ ExaCheckGetSpans (DrawablePtr pDrawable, int nspans, char *pdstStart) { - exaWaitSync(pDrawable->pScreen); + exaPrepareAccess (pDrawable, EXA_PREPARE_SRC); fbGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + exaFinishAccess (pDrawable, EXA_PREPARE_SRC); } void @@ -224,9 +242,9 @@ ExaCheckSaveAreas (PixmapPtr pPixmap, int yorg, WindowPtr pWin) { - exaWaitSync(pWin->drawable.pScreen); - exaDrawableDirty (&pPixmap->drawable); + exaPrepareAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST); fbSaveAreas (pPixmap, prgnSave, xorg, yorg, pWin); + exaFinishAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST); } void @@ -236,17 +254,17 @@ ExaCheckRestoreAreas (PixmapPtr pPixmap, int yorg, WindowPtr pWin) { - exaWaitSync(pWin->drawable.pScreen); - exaDrawableDirty ((DrawablePtr)pWin); + exaPrepareAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST); fbRestoreAreas (pPixmap, prgnSave, xorg, yorg, pWin); + exaFinishAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST); } void ExaCheckPaintWindow (WindowPtr pWin, RegionPtr pRegion, int what) { - exaWaitSync (pWin->drawable.pScreen); - exaDrawableDirty ((DrawablePtr)pWin); + exaPrepareAccess (&pWin->drawable, EXA_PREPARE_DEST); fbPaintWindow (pWin, pRegion, what); + exaFinishAccess (&pWin->drawable, EXA_PREPARE_DEST); } void @@ -263,8 +281,10 @@ ExaCheckComposite (CARD8 op, CARD16 width, CARD16 height) { - exaWaitSync (pDst->pDrawable->pScreen); - exaDrawableDirty (pDst->pDrawable); + exaPrepareAccess (pDst->pDrawable, EXA_PREPARE_DEST); + exaPrepareAccess (pSrc->pDrawable, EXA_PREPARE_SRC); + if (pMask) + exaPrepareAccess (pMask->pDrawable, EXA_PREPARE_MASK); fbComposite (op, pSrc, pMask, @@ -277,6 +297,10 @@ ExaCheckComposite (CARD8 op, yDst, width, height); + if (pMask) + exaFinishAccess (pMask->pDrawable, EXA_PREPARE_MASK); + exaFinishAccess (pSrc->pDrawable, EXA_PREPARE_SRC); + exaFinishAccess (pDst->pDrawable, EXA_PREPARE_DEST); } /* diff --git a/hw/xfree86/exa/exapict.c b/hw/xfree86/exa/exapict.c index 5bfb07c4b..537f159e0 100644 --- a/hw/xfree86/exa/exapict.c +++ b/hw/xfree86/exa/exapict.c @@ -262,13 +262,8 @@ exaTryDriverSolidFill(PicturePtr pSrc, else pSrcPix = (PixmapPtr) (pSrc->pDrawable); - /* If source is offscreen, we need to sync the accelerator - * before accessing it. We'd prefer for it to be in memory. - */ - if (exaPixmapIsOffscreen(pSrcPix)) { - exaWaitSync(pDst->pDrawable->pScreen); - } + exaPrepareAccess(&pSrcPix->drawable, EXA_PREPARE_SRC); pixel = *(CARD32 *)(pSrcPix->devPrivate.ptr); if (!exaGetRGBAFromPixel(pixel, &red, &green, &blue, &alpha, pSrc->format)) @@ -276,6 +271,8 @@ exaTryDriverSolidFill(PicturePtr pSrc, REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return -1; } + exaFinishAccess(&pSrcPix->drawable, EXA_PREPARE_SRC); + exaGetPixelFromRGBA(&pixel, red, green, blue, alpha, pDst->format);