From 6a29c4cec156a135d1d9cdb65995f7a84de7cb56 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 21 Sep 2005 07:43:01 +0000 Subject: [PATCH] Add support for hardware accelerating tiled background painting. One example of this is the root weave, which paints slightly slower on SiS now in my testing. However, according to keithp some apps use this feature for a sort of cheap backing store, which this could help with significantly. While I haven't done much performance testing with it, it will at least rule out one possible source of terrible performance. --- exa/exa.c | 146 ++++++++++++++++++++------------- exa/exa_accel.c | 146 ++++++++++++++++++++------------- exa/exa_migration.c | 146 ++++++++++++++++++++------------- hw/xfree86/exa/exa.c | 146 ++++++++++++++++++++------------- hw/xfree86/exa/exa_accel.c | 146 ++++++++++++++++++++------------- hw/xfree86/exa/exa_migration.c | 146 ++++++++++++++++++++------------- 6 files changed, 546 insertions(+), 330 deletions(-) diff --git a/exa/exa.c b/exa/exa.c index 8ba5dc6a8..964690ec1 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -560,52 +560,6 @@ exaFinishAccess(DrawablePtr pDrawable, int index) (*pExaScr->info->accel.FinishAccess) (pPixmap, index); } -#if 0 -static void -exaFillTiled(int dst_x, - int dst_y, - int width, - int height, - int src_x, - int src_y, - int src_width, - int src_height, - void (*Copy) (int srcX, - int srcY, - int dstX, - int dstY, - int width, - int height)) -{ - modulus (src_x, src_width, src_x); - modulus (src_y, src_height, src_y); - - while (height) - { - int dst_x_tmp = dst_x; - int src_x_tmp = src_x; - int width_tmp = width; - int height_left = src_height - src_y; - int height_this = min (height, height_left); - - while (width_tmp) - { - int width_left = src_width - src_x_tmp; - int width_this = min (width_tmp, width_left); - - (*Copy) (src_x_tmp, src_y, - dst_x_tmp, dst_y, - width_this, height_this); - - width_tmp -= width_this; - dst_x_tmp += width_this; - } - height -= height_this; - dst_y += height_this; - src_y = 0; - } -} -#endif static void exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, @@ -1240,6 +1194,95 @@ exaFillRegionSolid (DrawablePtr pDrawable, } } +/* Try to do an accelerated tile of the pTile into pRegion of pDrawable. + * Based on fbFillRegionTiled(), fbTile(). + */ +static void +exaFillRegionTiled (DrawablePtr pDrawable, + RegionPtr pRegion, + PixmapPtr pTile) +{ + ExaScreenPriv(pDrawable->pScreen); + PixmapPtr pPixmap; + int xoff, yoff; + int tileWidth, tileHeight; + + STRACE; + tileWidth = pTile->drawable.width; + tileHeight = pTile->drawable.height; + + if (pDrawable->width > pExaScr->info->card.maxX || + pDrawable->height > pExaScr->info->card.maxY || + tileWidth > pExaScr->info->card.maxX || + tileHeight > pExaScr->info->card.maxY) + { + goto fallback; + } + + pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); + if (!pPixmap) + goto fallback; + + exaPixmapUseScreen(pTile); + if (!exaPixmapIsOffscreen(pTile)) + goto fallback; + + if ((*pExaScr->info->accel.PrepareCopy) (pTile, pPixmap, 0, 0, GXcopy, + FB_ALLONES)) + { + int nbox = REGION_NUM_RECTS (pRegion); + BoxPtr pBox = REGION_RECTS (pRegion); + int xRot = pDrawable->x + xoff; + int yRot = pDrawable->y + yoff; + + while (nbox--) + { + int height = pBox->y2 - pBox->y1; + int dstY = pBox->y1 + yoff; + int tileY; + + modulus (dstY - yRot, tileHeight, tileY); + while (height > 0) { + int width = pBox->x2 - pBox->x1; + int dstX = pBox->x1 + xoff; + int tileX; + int h = tileHeight - tileY; + + if (h > height) + h = height; + height -= h; + + modulus (dstX - xRot, tileWidth, tileX); + while (width > 0) { + int w = tileWidth - tileX; + if (w > width) + w = width; + width -= w; + + (*pExaScr->info->accel.Copy) (pPixmap, + tileX, tileY, + dstX, dstY, + w, h); + dstX += w; + tileX = 0; + } + dstY += h; + tileY = 0; + } + pBox++; + } + (*pExaScr->info->accel.DoneCopy) (pPixmap); + exaMarkSync(pDrawable->pScreen); + exaDrawableDirty (pDrawable); + return; + } + +fallback: + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbFillRegionTiled (pDrawable, pRegion, pTile); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); +} + static void exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) { @@ -1265,26 +1308,19 @@ exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) case BackgroundPixel: exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel); return; -#if 0 case BackgroundPixmap: exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap); return; -#endif } break; case PW_BORDER: - if (pWin->borderIsPixel) - { + if (pWin->borderIsPixel) { exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel); return; - } -#if 0 - else - { + } else { exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap); return; } -#endif break; } } diff --git a/exa/exa_accel.c b/exa/exa_accel.c index 8ba5dc6a8..964690ec1 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -560,52 +560,6 @@ exaFinishAccess(DrawablePtr pDrawable, int index) (*pExaScr->info->accel.FinishAccess) (pPixmap, index); } -#if 0 -static void -exaFillTiled(int dst_x, - int dst_y, - int width, - int height, - int src_x, - int src_y, - int src_width, - int src_height, - void (*Copy) (int srcX, - int srcY, - int dstX, - int dstY, - int width, - int height)) -{ - modulus (src_x, src_width, src_x); - modulus (src_y, src_height, src_y); - - while (height) - { - int dst_x_tmp = dst_x; - int src_x_tmp = src_x; - int width_tmp = width; - int height_left = src_height - src_y; - int height_this = min (height, height_left); - - while (width_tmp) - { - int width_left = src_width - src_x_tmp; - int width_this = min (width_tmp, width_left); - - (*Copy) (src_x_tmp, src_y, - dst_x_tmp, dst_y, - width_this, height_this); - - width_tmp -= width_this; - dst_x_tmp += width_this; - } - height -= height_this; - dst_y += height_this; - src_y = 0; - } -} -#endif static void exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, @@ -1240,6 +1194,95 @@ exaFillRegionSolid (DrawablePtr pDrawable, } } +/* Try to do an accelerated tile of the pTile into pRegion of pDrawable. + * Based on fbFillRegionTiled(), fbTile(). + */ +static void +exaFillRegionTiled (DrawablePtr pDrawable, + RegionPtr pRegion, + PixmapPtr pTile) +{ + ExaScreenPriv(pDrawable->pScreen); + PixmapPtr pPixmap; + int xoff, yoff; + int tileWidth, tileHeight; + + STRACE; + tileWidth = pTile->drawable.width; + tileHeight = pTile->drawable.height; + + if (pDrawable->width > pExaScr->info->card.maxX || + pDrawable->height > pExaScr->info->card.maxY || + tileWidth > pExaScr->info->card.maxX || + tileHeight > pExaScr->info->card.maxY) + { + goto fallback; + } + + pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); + if (!pPixmap) + goto fallback; + + exaPixmapUseScreen(pTile); + if (!exaPixmapIsOffscreen(pTile)) + goto fallback; + + if ((*pExaScr->info->accel.PrepareCopy) (pTile, pPixmap, 0, 0, GXcopy, + FB_ALLONES)) + { + int nbox = REGION_NUM_RECTS (pRegion); + BoxPtr pBox = REGION_RECTS (pRegion); + int xRot = pDrawable->x + xoff; + int yRot = pDrawable->y + yoff; + + while (nbox--) + { + int height = pBox->y2 - pBox->y1; + int dstY = pBox->y1 + yoff; + int tileY; + + modulus (dstY - yRot, tileHeight, tileY); + while (height > 0) { + int width = pBox->x2 - pBox->x1; + int dstX = pBox->x1 + xoff; + int tileX; + int h = tileHeight - tileY; + + if (h > height) + h = height; + height -= h; + + modulus (dstX - xRot, tileWidth, tileX); + while (width > 0) { + int w = tileWidth - tileX; + if (w > width) + w = width; + width -= w; + + (*pExaScr->info->accel.Copy) (pPixmap, + tileX, tileY, + dstX, dstY, + w, h); + dstX += w; + tileX = 0; + } + dstY += h; + tileY = 0; + } + pBox++; + } + (*pExaScr->info->accel.DoneCopy) (pPixmap); + exaMarkSync(pDrawable->pScreen); + exaDrawableDirty (pDrawable); + return; + } + +fallback: + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbFillRegionTiled (pDrawable, pRegion, pTile); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); +} + static void exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) { @@ -1265,26 +1308,19 @@ exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) case BackgroundPixel: exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel); return; -#if 0 case BackgroundPixmap: exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap); return; -#endif } break; case PW_BORDER: - if (pWin->borderIsPixel) - { + if (pWin->borderIsPixel) { exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel); return; - } -#if 0 - else - { + } else { exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap); return; } -#endif break; } } diff --git a/exa/exa_migration.c b/exa/exa_migration.c index 8ba5dc6a8..964690ec1 100644 --- a/exa/exa_migration.c +++ b/exa/exa_migration.c @@ -560,52 +560,6 @@ exaFinishAccess(DrawablePtr pDrawable, int index) (*pExaScr->info->accel.FinishAccess) (pPixmap, index); } -#if 0 -static void -exaFillTiled(int dst_x, - int dst_y, - int width, - int height, - int src_x, - int src_y, - int src_width, - int src_height, - void (*Copy) (int srcX, - int srcY, - int dstX, - int dstY, - int width, - int height)) -{ - modulus (src_x, src_width, src_x); - modulus (src_y, src_height, src_y); - - while (height) - { - int dst_x_tmp = dst_x; - int src_x_tmp = src_x; - int width_tmp = width; - int height_left = src_height - src_y; - int height_this = min (height, height_left); - - while (width_tmp) - { - int width_left = src_width - src_x_tmp; - int width_this = min (width_tmp, width_left); - - (*Copy) (src_x_tmp, src_y, - dst_x_tmp, dst_y, - width_this, height_this); - - width_tmp -= width_this; - dst_x_tmp += width_this; - } - height -= height_this; - dst_y += height_this; - src_y = 0; - } -} -#endif static void exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, @@ -1240,6 +1194,95 @@ exaFillRegionSolid (DrawablePtr pDrawable, } } +/* Try to do an accelerated tile of the pTile into pRegion of pDrawable. + * Based on fbFillRegionTiled(), fbTile(). + */ +static void +exaFillRegionTiled (DrawablePtr pDrawable, + RegionPtr pRegion, + PixmapPtr pTile) +{ + ExaScreenPriv(pDrawable->pScreen); + PixmapPtr pPixmap; + int xoff, yoff; + int tileWidth, tileHeight; + + STRACE; + tileWidth = pTile->drawable.width; + tileHeight = pTile->drawable.height; + + if (pDrawable->width > pExaScr->info->card.maxX || + pDrawable->height > pExaScr->info->card.maxY || + tileWidth > pExaScr->info->card.maxX || + tileHeight > pExaScr->info->card.maxY) + { + goto fallback; + } + + pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); + if (!pPixmap) + goto fallback; + + exaPixmapUseScreen(pTile); + if (!exaPixmapIsOffscreen(pTile)) + goto fallback; + + if ((*pExaScr->info->accel.PrepareCopy) (pTile, pPixmap, 0, 0, GXcopy, + FB_ALLONES)) + { + int nbox = REGION_NUM_RECTS (pRegion); + BoxPtr pBox = REGION_RECTS (pRegion); + int xRot = pDrawable->x + xoff; + int yRot = pDrawable->y + yoff; + + while (nbox--) + { + int height = pBox->y2 - pBox->y1; + int dstY = pBox->y1 + yoff; + int tileY; + + modulus (dstY - yRot, tileHeight, tileY); + while (height > 0) { + int width = pBox->x2 - pBox->x1; + int dstX = pBox->x1 + xoff; + int tileX; + int h = tileHeight - tileY; + + if (h > height) + h = height; + height -= h; + + modulus (dstX - xRot, tileWidth, tileX); + while (width > 0) { + int w = tileWidth - tileX; + if (w > width) + w = width; + width -= w; + + (*pExaScr->info->accel.Copy) (pPixmap, + tileX, tileY, + dstX, dstY, + w, h); + dstX += w; + tileX = 0; + } + dstY += h; + tileY = 0; + } + pBox++; + } + (*pExaScr->info->accel.DoneCopy) (pPixmap); + exaMarkSync(pDrawable->pScreen); + exaDrawableDirty (pDrawable); + return; + } + +fallback: + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbFillRegionTiled (pDrawable, pRegion, pTile); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); +} + static void exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) { @@ -1265,26 +1308,19 @@ exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) case BackgroundPixel: exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel); return; -#if 0 case BackgroundPixmap: exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap); return; -#endif } break; case PW_BORDER: - if (pWin->borderIsPixel) - { + if (pWin->borderIsPixel) { exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel); return; - } -#if 0 - else - { + } else { exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap); return; } -#endif break; } } diff --git a/hw/xfree86/exa/exa.c b/hw/xfree86/exa/exa.c index 8ba5dc6a8..964690ec1 100644 --- a/hw/xfree86/exa/exa.c +++ b/hw/xfree86/exa/exa.c @@ -560,52 +560,6 @@ exaFinishAccess(DrawablePtr pDrawable, int index) (*pExaScr->info->accel.FinishAccess) (pPixmap, index); } -#if 0 -static void -exaFillTiled(int dst_x, - int dst_y, - int width, - int height, - int src_x, - int src_y, - int src_width, - int src_height, - void (*Copy) (int srcX, - int srcY, - int dstX, - int dstY, - int width, - int height)) -{ - modulus (src_x, src_width, src_x); - modulus (src_y, src_height, src_y); - - while (height) - { - int dst_x_tmp = dst_x; - int src_x_tmp = src_x; - int width_tmp = width; - int height_left = src_height - src_y; - int height_this = min (height, height_left); - - while (width_tmp) - { - int width_left = src_width - src_x_tmp; - int width_this = min (width_tmp, width_left); - - (*Copy) (src_x_tmp, src_y, - dst_x_tmp, dst_y, - width_this, height_this); - - width_tmp -= width_this; - dst_x_tmp += width_this; - } - height -= height_this; - dst_y += height_this; - src_y = 0; - } -} -#endif static void exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, @@ -1240,6 +1194,95 @@ exaFillRegionSolid (DrawablePtr pDrawable, } } +/* Try to do an accelerated tile of the pTile into pRegion of pDrawable. + * Based on fbFillRegionTiled(), fbTile(). + */ +static void +exaFillRegionTiled (DrawablePtr pDrawable, + RegionPtr pRegion, + PixmapPtr pTile) +{ + ExaScreenPriv(pDrawable->pScreen); + PixmapPtr pPixmap; + int xoff, yoff; + int tileWidth, tileHeight; + + STRACE; + tileWidth = pTile->drawable.width; + tileHeight = pTile->drawable.height; + + if (pDrawable->width > pExaScr->info->card.maxX || + pDrawable->height > pExaScr->info->card.maxY || + tileWidth > pExaScr->info->card.maxX || + tileHeight > pExaScr->info->card.maxY) + { + goto fallback; + } + + pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); + if (!pPixmap) + goto fallback; + + exaPixmapUseScreen(pTile); + if (!exaPixmapIsOffscreen(pTile)) + goto fallback; + + if ((*pExaScr->info->accel.PrepareCopy) (pTile, pPixmap, 0, 0, GXcopy, + FB_ALLONES)) + { + int nbox = REGION_NUM_RECTS (pRegion); + BoxPtr pBox = REGION_RECTS (pRegion); + int xRot = pDrawable->x + xoff; + int yRot = pDrawable->y + yoff; + + while (nbox--) + { + int height = pBox->y2 - pBox->y1; + int dstY = pBox->y1 + yoff; + int tileY; + + modulus (dstY - yRot, tileHeight, tileY); + while (height > 0) { + int width = pBox->x2 - pBox->x1; + int dstX = pBox->x1 + xoff; + int tileX; + int h = tileHeight - tileY; + + if (h > height) + h = height; + height -= h; + + modulus (dstX - xRot, tileWidth, tileX); + while (width > 0) { + int w = tileWidth - tileX; + if (w > width) + w = width; + width -= w; + + (*pExaScr->info->accel.Copy) (pPixmap, + tileX, tileY, + dstX, dstY, + w, h); + dstX += w; + tileX = 0; + } + dstY += h; + tileY = 0; + } + pBox++; + } + (*pExaScr->info->accel.DoneCopy) (pPixmap); + exaMarkSync(pDrawable->pScreen); + exaDrawableDirty (pDrawable); + return; + } + +fallback: + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbFillRegionTiled (pDrawable, pRegion, pTile); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); +} + static void exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) { @@ -1265,26 +1308,19 @@ exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) case BackgroundPixel: exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel); return; -#if 0 case BackgroundPixmap: exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap); return; -#endif } break; case PW_BORDER: - if (pWin->borderIsPixel) - { + if (pWin->borderIsPixel) { exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel); return; - } -#if 0 - else - { + } else { exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap); return; } -#endif break; } } diff --git a/hw/xfree86/exa/exa_accel.c b/hw/xfree86/exa/exa_accel.c index 8ba5dc6a8..964690ec1 100644 --- a/hw/xfree86/exa/exa_accel.c +++ b/hw/xfree86/exa/exa_accel.c @@ -560,52 +560,6 @@ exaFinishAccess(DrawablePtr pDrawable, int index) (*pExaScr->info->accel.FinishAccess) (pPixmap, index); } -#if 0 -static void -exaFillTiled(int dst_x, - int dst_y, - int width, - int height, - int src_x, - int src_y, - int src_width, - int src_height, - void (*Copy) (int srcX, - int srcY, - int dstX, - int dstY, - int width, - int height)) -{ - modulus (src_x, src_width, src_x); - modulus (src_y, src_height, src_y); - - while (height) - { - int dst_x_tmp = dst_x; - int src_x_tmp = src_x; - int width_tmp = width; - int height_left = src_height - src_y; - int height_this = min (height, height_left); - - while (width_tmp) - { - int width_left = src_width - src_x_tmp; - int width_this = min (width_tmp, width_left); - - (*Copy) (src_x_tmp, src_y, - dst_x_tmp, dst_y, - width_this, height_this); - - width_tmp -= width_this; - dst_x_tmp += width_this; - } - height -= height_this; - dst_y += height_this; - src_y = 0; - } -} -#endif static void exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, @@ -1240,6 +1194,95 @@ exaFillRegionSolid (DrawablePtr pDrawable, } } +/* Try to do an accelerated tile of the pTile into pRegion of pDrawable. + * Based on fbFillRegionTiled(), fbTile(). + */ +static void +exaFillRegionTiled (DrawablePtr pDrawable, + RegionPtr pRegion, + PixmapPtr pTile) +{ + ExaScreenPriv(pDrawable->pScreen); + PixmapPtr pPixmap; + int xoff, yoff; + int tileWidth, tileHeight; + + STRACE; + tileWidth = pTile->drawable.width; + tileHeight = pTile->drawable.height; + + if (pDrawable->width > pExaScr->info->card.maxX || + pDrawable->height > pExaScr->info->card.maxY || + tileWidth > pExaScr->info->card.maxX || + tileHeight > pExaScr->info->card.maxY) + { + goto fallback; + } + + pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); + if (!pPixmap) + goto fallback; + + exaPixmapUseScreen(pTile); + if (!exaPixmapIsOffscreen(pTile)) + goto fallback; + + if ((*pExaScr->info->accel.PrepareCopy) (pTile, pPixmap, 0, 0, GXcopy, + FB_ALLONES)) + { + int nbox = REGION_NUM_RECTS (pRegion); + BoxPtr pBox = REGION_RECTS (pRegion); + int xRot = pDrawable->x + xoff; + int yRot = pDrawable->y + yoff; + + while (nbox--) + { + int height = pBox->y2 - pBox->y1; + int dstY = pBox->y1 + yoff; + int tileY; + + modulus (dstY - yRot, tileHeight, tileY); + while (height > 0) { + int width = pBox->x2 - pBox->x1; + int dstX = pBox->x1 + xoff; + int tileX; + int h = tileHeight - tileY; + + if (h > height) + h = height; + height -= h; + + modulus (dstX - xRot, tileWidth, tileX); + while (width > 0) { + int w = tileWidth - tileX; + if (w > width) + w = width; + width -= w; + + (*pExaScr->info->accel.Copy) (pPixmap, + tileX, tileY, + dstX, dstY, + w, h); + dstX += w; + tileX = 0; + } + dstY += h; + tileY = 0; + } + pBox++; + } + (*pExaScr->info->accel.DoneCopy) (pPixmap); + exaMarkSync(pDrawable->pScreen); + exaDrawableDirty (pDrawable); + return; + } + +fallback: + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbFillRegionTiled (pDrawable, pRegion, pTile); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); +} + static void exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) { @@ -1265,26 +1308,19 @@ exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) case BackgroundPixel: exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel); return; -#if 0 case BackgroundPixmap: exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap); return; -#endif } break; case PW_BORDER: - if (pWin->borderIsPixel) - { + if (pWin->borderIsPixel) { exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel); return; - } -#if 0 - else - { + } else { exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap); return; } -#endif break; } } diff --git a/hw/xfree86/exa/exa_migration.c b/hw/xfree86/exa/exa_migration.c index 8ba5dc6a8..964690ec1 100644 --- a/hw/xfree86/exa/exa_migration.c +++ b/hw/xfree86/exa/exa_migration.c @@ -560,52 +560,6 @@ exaFinishAccess(DrawablePtr pDrawable, int index) (*pExaScr->info->accel.FinishAccess) (pPixmap, index); } -#if 0 -static void -exaFillTiled(int dst_x, - int dst_y, - int width, - int height, - int src_x, - int src_y, - int src_width, - int src_height, - void (*Copy) (int srcX, - int srcY, - int dstX, - int dstY, - int width, - int height)) -{ - modulus (src_x, src_width, src_x); - modulus (src_y, src_height, src_y); - - while (height) - { - int dst_x_tmp = dst_x; - int src_x_tmp = src_x; - int width_tmp = width; - int height_left = src_height - src_y; - int height_this = min (height, height_left); - - while (width_tmp) - { - int width_left = src_width - src_x_tmp; - int width_this = min (width_tmp, width_left); - - (*Copy) (src_x_tmp, src_y, - dst_x_tmp, dst_y, - width_this, height_this); - - width_tmp -= width_this; - dst_x_tmp += width_this; - } - height -= height_this; - dst_y += height_this; - src_y = 0; - } -} -#endif static void exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, @@ -1240,6 +1194,95 @@ exaFillRegionSolid (DrawablePtr pDrawable, } } +/* Try to do an accelerated tile of the pTile into pRegion of pDrawable. + * Based on fbFillRegionTiled(), fbTile(). + */ +static void +exaFillRegionTiled (DrawablePtr pDrawable, + RegionPtr pRegion, + PixmapPtr pTile) +{ + ExaScreenPriv(pDrawable->pScreen); + PixmapPtr pPixmap; + int xoff, yoff; + int tileWidth, tileHeight; + + STRACE; + tileWidth = pTile->drawable.width; + tileHeight = pTile->drawable.height; + + if (pDrawable->width > pExaScr->info->card.maxX || + pDrawable->height > pExaScr->info->card.maxY || + tileWidth > pExaScr->info->card.maxX || + tileHeight > pExaScr->info->card.maxY) + { + goto fallback; + } + + pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); + if (!pPixmap) + goto fallback; + + exaPixmapUseScreen(pTile); + if (!exaPixmapIsOffscreen(pTile)) + goto fallback; + + if ((*pExaScr->info->accel.PrepareCopy) (pTile, pPixmap, 0, 0, GXcopy, + FB_ALLONES)) + { + int nbox = REGION_NUM_RECTS (pRegion); + BoxPtr pBox = REGION_RECTS (pRegion); + int xRot = pDrawable->x + xoff; + int yRot = pDrawable->y + yoff; + + while (nbox--) + { + int height = pBox->y2 - pBox->y1; + int dstY = pBox->y1 + yoff; + int tileY; + + modulus (dstY - yRot, tileHeight, tileY); + while (height > 0) { + int width = pBox->x2 - pBox->x1; + int dstX = pBox->x1 + xoff; + int tileX; + int h = tileHeight - tileY; + + if (h > height) + h = height; + height -= h; + + modulus (dstX - xRot, tileWidth, tileX); + while (width > 0) { + int w = tileWidth - tileX; + if (w > width) + w = width; + width -= w; + + (*pExaScr->info->accel.Copy) (pPixmap, + tileX, tileY, + dstX, dstY, + w, h); + dstX += w; + tileX = 0; + } + dstY += h; + tileY = 0; + } + pBox++; + } + (*pExaScr->info->accel.DoneCopy) (pPixmap); + exaMarkSync(pDrawable->pScreen); + exaDrawableDirty (pDrawable); + return; + } + +fallback: + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbFillRegionTiled (pDrawable, pRegion, pTile); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); +} + static void exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) { @@ -1265,26 +1308,19 @@ exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) case BackgroundPixel: exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel); return; -#if 0 case BackgroundPixmap: exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap); return; -#endif } break; case PW_BORDER: - if (pWin->borderIsPixel) - { + if (pWin->borderIsPixel) { exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel); return; - } -#if 0 - else - { + } else { exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap); return; } -#endif break; } }