diff options
-rw-r--r-- | dix/dispatch.c | 1 | ||||
-rw-r--r-- | dix/pixmap.c | 106 | ||||
-rw-r--r-- | include/pixmap.h | 16 | ||||
-rw-r--r-- | include/pixmapstr.h | 8 | ||||
-rw-r--r-- | include/scrnintstr.h | 2 |
5 files changed, 133 insertions, 0 deletions
diff --git a/dix/dispatch.c b/dix/dispatch.c index 29ac5a45a..bc803d78f 100644 --- a/dix/dispatch.c +++ b/dix/dispatch.c @@ -3742,6 +3742,7 @@ static int init_screen(ScreenPtr pScreen, int i, Bool gpu) pScreen->ClipNotify = 0; /* for R4 ddx compatibility */ pScreen->CreateScreenResources = 0; + xorg_list_init(&pScreen->pixmap_dirty_list); xorg_list_init(&pScreen->unattached_list); xorg_list_init(&pScreen->output_slave_list); diff --git a/dix/pixmap.c b/dix/pixmap.c index 11b1b049e..9163e99eb 100644 --- a/dix/pixmap.c +++ b/dix/pixmap.c @@ -158,3 +158,109 @@ PixmapPtr PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave) return spix; } + +Bool +PixmapStartDirtyTracking(PixmapPtr src, + PixmapPtr slave_dst, + int x, int y) +{ + ScreenPtr screen = src->drawable.pScreen; + PixmapDirtyUpdatePtr dirty_update; + + dirty_update = calloc(1, sizeof(PixmapDirtyUpdateRec)); + if (!dirty_update) + return FALSE; + + dirty_update->src = src; + dirty_update->slave_dst = slave_dst; + dirty_update->x = x; + dirty_update->y = y; + + dirty_update->damage = DamageCreate(NULL, NULL, + DamageReportNone, + TRUE, src->drawable.pScreen, + src->drawable.pScreen); + if (!dirty_update->damage) { + free(dirty_update); + return FALSE; + } + + DamageRegister(&src->drawable, dirty_update->damage); + xorg_list_add(&dirty_update->ent, &screen->pixmap_dirty_list); + return TRUE; +} + +Bool +PixmapStopDirtyTracking(PixmapPtr src, PixmapPtr slave_dst) +{ + ScreenPtr screen = src->drawable.pScreen; + PixmapDirtyUpdatePtr ent, safe; + + xorg_list_for_each_entry_safe(ent, safe, &screen->pixmap_dirty_list, ent) { + if (ent->src == src && ent->slave_dst == slave_dst) { + DamageUnregister(&src->drawable, ent->damage); + DamageDestroy(ent->damage); + xorg_list_del(&ent->ent); + free(ent); + } + } + return TRUE; +} + +/* + * this function can possibly be improved and optimised, by clipping + * instead of iterating + */ +Bool PixmapSyncDirtyHelper(PixmapDirtyUpdatePtr dirty, RegionPtr dirty_region) +{ + ScreenPtr pScreen = dirty->src->drawable.pScreen; + int n; + BoxPtr b; + RegionPtr region = DamageRegion(dirty->damage); + GCPtr pGC; + PixmapPtr dst; + SourceValidateProcPtr SourceValidate; + + /* + * SourceValidate is used by the software cursor code + * to pull the cursor off of the screen when reading + * bits from the frame buffer. Bypassing this function + * leaves the software cursor in place + */ + SourceValidate = pScreen->SourceValidate; + pScreen->SourceValidate = NULL; + + RegionTranslate(dirty_region, dirty->x, dirty->y); + RegionIntersect(dirty_region, dirty_region, region); + + if (RegionNil(dirty_region)) { + RegionUninit(dirty_region); + return FALSE; + } + + dst = dirty->slave_dst->master_pixmap; + + RegionTranslate(dirty_region, -dirty->x, -dirty->y); + n = RegionNumRects(dirty_region); + b = RegionRects(dirty_region); + + pGC = GetScratchGC(dirty->src->drawable.depth, pScreen); + ValidateGC(&dst->drawable, pGC); + + while (n--) { + BoxRec dst_box; + int w, h; + + dst_box = *b; + w = dst_box.x2 - dst_box.x1; + h = dst_box.y2 - dst_box.y1; + + pGC->ops->CopyArea(&dirty->src->drawable, &dst->drawable, pGC, + dirty->x + dst_box.x1, dirty->y + dst_box.y1, w, h, dst_box.x1, dst_box.y1); + b++; + } + FreeScratchGC(pGC); + + pScreen->SourceValidate = SourceValidate; + return TRUE; +} diff --git a/include/pixmap.h b/include/pixmap.h index 8c523bdd9..921a94d1e 100644 --- a/include/pixmap.h +++ b/include/pixmap.h @@ -49,6 +49,7 @@ SOFTWARE. #include "misc.h" #include "screenint.h" +#include "regionstr.h" /* types for Drawable */ #define DRAWABLE_WINDOW 0 @@ -73,6 +74,8 @@ SOFTWARE. typedef struct _Drawable *DrawablePtr; typedef struct _Pixmap *PixmapPtr; +typedef struct _PixmapDirtyUpdate *PixmapDirtyUpdatePtr; + typedef union _PixUnion { PixmapPtr pixmap; unsigned long pixel; @@ -112,4 +115,17 @@ extern _X_EXPORT void FreePixmap(PixmapPtr /*pPixmap */ ); extern _X_EXPORT PixmapPtr PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave); +extern _X_EXPORT Bool +PixmapStartDirtyTracking(PixmapPtr src, + PixmapPtr slave_dst, + int x, int y); + +extern _X_EXPORT Bool +PixmapStopDirtyTracking(PixmapPtr src, PixmapPtr slave_dst); + +/* helper function, drivers can do this themselves if they can do it more + efficently */ +extern _X_EXPORT Bool +PixmapSyncDirtyHelper(PixmapDirtyUpdatePtr dirty, RegionPtr dirty_region); + #endif /* PIXMAP_H */ diff --git a/include/pixmapstr.h b/include/pixmapstr.h index 40af5c4a3..2a1ef9b85 100644 --- a/include/pixmapstr.h +++ b/include/pixmapstr.h @@ -50,6 +50,7 @@ SOFTWARE. #include "screenint.h" #include "regionstr.h" #include "privates.h" +#include "damage.h" typedef struct _Drawable { unsigned char type; /* DRAWABLE_<type> */ @@ -84,6 +85,13 @@ typedef struct _Pixmap { PixmapPtr master_pixmap; /* pointer to master copy of pixmap for pixmap sharing */ } PixmapRec; +typedef struct _PixmapDirtyUpdate { + PixmapPtr src, slave_dst; + int x, y; + DamagePtr damage; + struct xorg_list ent; +} PixmapDirtyUpdateRec; + static inline void PixmapBox(BoxPtr box, PixmapPtr pixmap) { diff --git a/include/scrnintstr.h b/include/scrnintstr.h index 3a738d3b0..5ef37ed9a 100644 --- a/include/scrnintstr.h +++ b/include/scrnintstr.h @@ -505,6 +505,8 @@ typedef struct _Screen { StartPixmapTrackingProcPtr StartPixmapTracking; StopPixmapTrackingProcPtr StopPixmapTracking; + + struct xorg_list pixmap_dirty_list; } ScreenRec; static inline RegionPtr |