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 <keithp@keithp.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
c5cc2a8243
commit
9b8217f9ef
|
@ -3742,6 +3742,7 @@ static int init_screen(ScreenPtr pScreen, int i, Bool gpu)
|
||||||
pScreen->ClipNotify = 0; /* for R4 ddx compatibility */
|
pScreen->ClipNotify = 0; /* for R4 ddx compatibility */
|
||||||
pScreen->CreateScreenResources = 0;
|
pScreen->CreateScreenResources = 0;
|
||||||
|
|
||||||
|
xorg_list_init(&pScreen->pixmap_dirty_list);
|
||||||
xorg_list_init(&pScreen->unattached_list);
|
xorg_list_init(&pScreen->unattached_list);
|
||||||
xorg_list_init(&pScreen->output_slave_list);
|
xorg_list_init(&pScreen->output_slave_list);
|
||||||
|
|
||||||
|
|
106
dix/pixmap.c
106
dix/pixmap.c
|
@ -158,3 +158,109 @@ PixmapPtr PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave)
|
||||||
|
|
||||||
return spix;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ SOFTWARE.
|
||||||
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "screenint.h"
|
#include "screenint.h"
|
||||||
|
#include "regionstr.h"
|
||||||
|
|
||||||
/* types for Drawable */
|
/* types for Drawable */
|
||||||
#define DRAWABLE_WINDOW 0
|
#define DRAWABLE_WINDOW 0
|
||||||
|
@ -73,6 +74,8 @@ SOFTWARE.
|
||||||
typedef struct _Drawable *DrawablePtr;
|
typedef struct _Drawable *DrawablePtr;
|
||||||
typedef struct _Pixmap *PixmapPtr;
|
typedef struct _Pixmap *PixmapPtr;
|
||||||
|
|
||||||
|
typedef struct _PixmapDirtyUpdate *PixmapDirtyUpdatePtr;
|
||||||
|
|
||||||
typedef union _PixUnion {
|
typedef union _PixUnion {
|
||||||
PixmapPtr pixmap;
|
PixmapPtr pixmap;
|
||||||
unsigned long pixel;
|
unsigned long pixel;
|
||||||
|
@ -112,4 +115,17 @@ extern _X_EXPORT void FreePixmap(PixmapPtr /*pPixmap */ );
|
||||||
extern _X_EXPORT PixmapPtr
|
extern _X_EXPORT PixmapPtr
|
||||||
PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave);
|
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 */
|
#endif /* PIXMAP_H */
|
||||||
|
|
|
@ -50,6 +50,7 @@ SOFTWARE.
|
||||||
#include "screenint.h"
|
#include "screenint.h"
|
||||||
#include "regionstr.h"
|
#include "regionstr.h"
|
||||||
#include "privates.h"
|
#include "privates.h"
|
||||||
|
#include "damage.h"
|
||||||
|
|
||||||
typedef struct _Drawable {
|
typedef struct _Drawable {
|
||||||
unsigned char type; /* DRAWABLE_<type> */
|
unsigned char type; /* DRAWABLE_<type> */
|
||||||
|
@ -84,6 +85,13 @@ typedef struct _Pixmap {
|
||||||
PixmapPtr master_pixmap; /* pointer to master copy of pixmap for pixmap sharing */
|
PixmapPtr master_pixmap; /* pointer to master copy of pixmap for pixmap sharing */
|
||||||
} PixmapRec;
|
} PixmapRec;
|
||||||
|
|
||||||
|
typedef struct _PixmapDirtyUpdate {
|
||||||
|
PixmapPtr src, slave_dst;
|
||||||
|
int x, y;
|
||||||
|
DamagePtr damage;
|
||||||
|
struct xorg_list ent;
|
||||||
|
} PixmapDirtyUpdateRec;
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
PixmapBox(BoxPtr box, PixmapPtr pixmap)
|
PixmapBox(BoxPtr box, PixmapPtr pixmap)
|
||||||
{
|
{
|
||||||
|
|
|
@ -505,6 +505,8 @@ typedef struct _Screen {
|
||||||
|
|
||||||
StartPixmapTrackingProcPtr StartPixmapTracking;
|
StartPixmapTrackingProcPtr StartPixmapTracking;
|
||||||
StopPixmapTrackingProcPtr StopPixmapTracking;
|
StopPixmapTrackingProcPtr StopPixmapTracking;
|
||||||
|
|
||||||
|
struct xorg_list pixmap_dirty_list;
|
||||||
} ScreenRec;
|
} ScreenRec;
|
||||||
|
|
||||||
static inline RegionPtr
|
static inline RegionPtr
|
||||||
|
|
Loading…
Reference in New Issue