Commit 9b8217f9 authored by Dave Airlie's avatar Dave Airlie

dix/pixmap: track dirty pixmaps in server. (v4)

This adds two functions for drivers to use directly to keep a
linked list of slave pixmaps to do damage tracking on and keep
updated. It also adds a helper function that drivers may optionally
call to do a simple copy area damage update.

v2: use damage.h not damagestr.h, fixes ephyr build.

v3: address ajax review: use slave_dst, drop unused dst member.

v4: check DamageCreate return, add SourceValidate comment,
add a comment addressing possible optimisation possibility
Reviewed-by: Keith Packard's avatarKeith Packard <>
Reviewed-by: Adam Jackson's avatarAdam Jackson <>
Signed-off-by: default avatarDave Airlie <>
parent c5cc2a82
......@@ -3742,6 +3742,7 @@ static int init_screen(ScreenPtr pScreen, int i, Bool gpu)
pScreen->ClipNotify = 0; /* for R4 ddx compatibility */
pScreen->CreateScreenResources = 0;
......@@ -158,3 +158,109 @@ PixmapPtr PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave)
return spix;
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,
TRUE, src->drawable.pScreen,
if (!dirty_update->damage) {
return FALSE;
DamageRegister(&src->drawable, dirty_update->damage);
xorg_list_add(&dirty_update->ent, &screen->pixmap_dirty_list);
return TRUE;
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);
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)) {
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);
pScreen->SourceValidate = SourceValidate;
return TRUE;
......@@ -49,6 +49,7 @@ SOFTWARE.
#include "misc.h"
#include "screenint.h"
#include "regionstr.h"
/* types for Drawable */
......@@ -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 */
......@@ -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)
......@@ -505,6 +505,8 @@ typedef struct _Screen {
StartPixmapTrackingProcPtr StartPixmapTracking;
StopPixmapTrackingProcPtr StopPixmapTracking;
struct xorg_list pixmap_dirty_list;
} ScreenRec;
static inline RegionPtr
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment