randr: add initial scanout pixmap support (v3)
When randr notices a crtc configuration request for a slave device, it checks if the slave allocated pixmap exists and is suitable, if not it allocates a new shared pixmap from the master, shares it to the slave, and starts the master tracking damage to it, to keep it updated from the current front pixmap. If the resize means the crtc is no longer used it will destroy the slave pixmap. This adds the concept of a scanout_pixmap to the randr_crtc object, and also adds a master pixmap pointer to the pixmap object, along with defining some pixmap helper functions for getting pixmap box/regions. v2: split out pixmap sharing to a separate function. v3: update for void * 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
0b0e714892
commit
f2da2c1204
29
dix/pixmap.c
29
dix/pixmap.c
|
@ -129,3 +129,32 @@ FreePixmap(PixmapPtr pPixmap)
|
||||||
dixFiniPrivates(pPixmap, PRIVATE_PIXMAP);
|
dixFiniPrivates(pPixmap, PRIVATE_PIXMAP);
|
||||||
free(pPixmap);
|
free(pPixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PixmapPtr PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave)
|
||||||
|
{
|
||||||
|
PixmapPtr spix;
|
||||||
|
int ret;
|
||||||
|
void *handle;
|
||||||
|
ScreenPtr master = pixmap->drawable.pScreen;
|
||||||
|
int depth = pixmap->drawable.depth;
|
||||||
|
|
||||||
|
ret = master->SharePixmapBacking(pixmap, slave, &handle);
|
||||||
|
if (ret == FALSE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
spix = slave->CreatePixmap(slave, 0, 0, depth,
|
||||||
|
CREATE_PIXMAP_USAGE_SHARED);
|
||||||
|
slave->ModifyPixmapHeader(spix, pixmap->drawable.width,
|
||||||
|
pixmap->drawable.height, depth, 0,
|
||||||
|
pixmap->devKind, NULL);
|
||||||
|
|
||||||
|
spix->master_pixmap = pixmap;
|
||||||
|
|
||||||
|
ret = slave->SetSharedPixmapBacking(spix, handle);
|
||||||
|
if (ret == FALSE) {
|
||||||
|
slave->DestroyPixmap(spix);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return spix;
|
||||||
|
}
|
||||||
|
|
|
@ -109,4 +109,7 @@ extern _X_EXPORT PixmapPtr AllocatePixmap(ScreenPtr /*pScreen */ ,
|
||||||
|
|
||||||
extern _X_EXPORT void FreePixmap(PixmapPtr /*pPixmap */ );
|
extern _X_EXPORT void FreePixmap(PixmapPtr /*pPixmap */ );
|
||||||
|
|
||||||
|
extern _X_EXPORT PixmapPtr
|
||||||
|
PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave);
|
||||||
|
|
||||||
#endif /* PIXMAP_H */
|
#endif /* PIXMAP_H */
|
||||||
|
|
|
@ -80,6 +80,28 @@ typedef struct _Pixmap {
|
||||||
short screen_y;
|
short screen_y;
|
||||||
#endif
|
#endif
|
||||||
unsigned usage_hint; /* see CREATE_PIXMAP_USAGE_* */
|
unsigned usage_hint; /* see CREATE_PIXMAP_USAGE_* */
|
||||||
|
|
||||||
|
PixmapPtr master_pixmap; /* pointer to master copy of pixmap for pixmap sharing */
|
||||||
} PixmapRec;
|
} PixmapRec;
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
PixmapBox(BoxPtr box, PixmapPtr pixmap)
|
||||||
|
{
|
||||||
|
box->x1 = 0;
|
||||||
|
box->x2 = pixmap->drawable.width;
|
||||||
|
|
||||||
|
box->y1 = 0;
|
||||||
|
box->y2 = pixmap->drawable.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
PixmapRegionInit(RegionPtr region, PixmapPtr pixmap)
|
||||||
|
{
|
||||||
|
BoxRec box;
|
||||||
|
|
||||||
|
PixmapBox(&box, pixmap);
|
||||||
|
RegionInit(region, &box, 1);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* PIXMAPSTRUCT_H */
|
#endif /* PIXMAPSTRUCT_H */
|
||||||
|
|
|
@ -127,6 +127,8 @@ struct _rrCrtc {
|
||||||
PictTransform transform;
|
PictTransform transform;
|
||||||
struct pict_f_transform f_transform;
|
struct pict_f_transform f_transform;
|
||||||
struct pict_f_transform f_inverse;
|
struct pict_f_transform f_inverse;
|
||||||
|
|
||||||
|
PixmapPtr scanout_pixmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _rrOutput {
|
struct _rrOutput {
|
||||||
|
@ -242,6 +244,8 @@ typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen,
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef Bool (*RRCrtcSetScanoutPixmapProcPtr)(RRCrtcPtr crtc, PixmapPtr pixmap);
|
||||||
|
|
||||||
typedef struct _rrScrPriv {
|
typedef struct _rrScrPriv {
|
||||||
/*
|
/*
|
||||||
* 'public' part of the structure; DDXen fill this in
|
* 'public' part of the structure; DDXen fill this in
|
||||||
|
@ -265,6 +269,8 @@ typedef struct _rrScrPriv {
|
||||||
RRGetPanningProcPtr rrGetPanning;
|
RRGetPanningProcPtr rrGetPanning;
|
||||||
RRSetPanningProcPtr rrSetPanning;
|
RRSetPanningProcPtr rrSetPanning;
|
||||||
#endif
|
#endif
|
||||||
|
/* TODO #if RANDR_15_INTERFACE */
|
||||||
|
RRCrtcSetScanoutPixmapProcPtr rrCrtcSetScanoutPixmap;
|
||||||
|
|
||||||
RRProviderGetPropertyProcPtr rrProviderGetProperty;
|
RRProviderGetPropertyProcPtr rrProviderGetProperty;
|
||||||
RRProviderSetPropertyProcPtr rrProviderSetProperty;
|
RRProviderSetPropertyProcPtr rrProviderSetProperty;
|
||||||
|
@ -648,6 +654,12 @@ extern _X_EXPORT Bool
|
||||||
extern _X_EXPORT void
|
extern _X_EXPORT void
|
||||||
RRCrtcInitErrorValue(void);
|
RRCrtcInitErrorValue(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Detach and free a scanout pixmap
|
||||||
|
*/
|
||||||
|
extern _X_EXPORT void
|
||||||
|
RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Crtc dispatch
|
* Crtc dispatch
|
||||||
*/
|
*/
|
||||||
|
|
171
randr/rrcrtc.c
171
randr/rrcrtc.c
|
@ -367,6 +367,154 @@ RRComputeContiguity(ScreenPtr pScreen)
|
||||||
pScrPriv->discontiguous = discontiguous;
|
pScrPriv->discontiguous = discontiguous;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc)
|
||||||
|
{
|
||||||
|
ScreenPtr master = crtc->pScreen->current_master;
|
||||||
|
int ret;
|
||||||
|
PixmapPtr mscreenpix;
|
||||||
|
rrScrPriv(crtc->pScreen);
|
||||||
|
|
||||||
|
mscreenpix = master->GetScreenPixmap(master);
|
||||||
|
|
||||||
|
ret = pScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL);
|
||||||
|
if (crtc->scanout_pixmap) {
|
||||||
|
master->StopPixmapTracking(mscreenpix, crtc->scanout_pixmap);
|
||||||
|
master->DestroyPixmap(crtc->scanout_pixmap->master_pixmap);
|
||||||
|
crtc->pScreen->DestroyPixmap(crtc->scanout_pixmap);
|
||||||
|
}
|
||||||
|
crtc->scanout_pixmap = NULL;
|
||||||
|
RRCrtcChanged(crtc, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bool
|
||||||
|
rrCreateSharedPixmap(RRCrtcPtr crtc, int width, int height,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
PixmapPtr mpix, spix;
|
||||||
|
ScreenPtr master = crtc->pScreen->current_master;
|
||||||
|
Bool ret;
|
||||||
|
int depth;
|
||||||
|
PixmapPtr mscreenpix;
|
||||||
|
PixmapPtr protopix = crtc->pScreen->current_master->GetScreenPixmap(crtc->pScreen->current_master);
|
||||||
|
rrScrPriv(crtc->pScreen);
|
||||||
|
|
||||||
|
/* create a pixmap on the master screen,
|
||||||
|
then get a shared handle for it
|
||||||
|
create a shared pixmap on the slave screen using the handle
|
||||||
|
set the master screen to do dirty updates to the shared pixmap
|
||||||
|
from the screen pixmap.
|
||||||
|
set slave screen to scanout shared linear pixmap
|
||||||
|
*/
|
||||||
|
|
||||||
|
mscreenpix = master->GetScreenPixmap(master);
|
||||||
|
depth = protopix->drawable.depth;
|
||||||
|
|
||||||
|
if (crtc->scanout_pixmap)
|
||||||
|
RRCrtcDetachScanoutPixmap(crtc);
|
||||||
|
|
||||||
|
if (width == 0 && height == 0) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpix = master->CreatePixmap(master, width, height, depth,
|
||||||
|
CREATE_PIXMAP_USAGE_SHARED);
|
||||||
|
if (!mpix)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
spix = PixmapShareToSlave(mpix, crtc->pScreen);
|
||||||
|
if (spix == NULL) {
|
||||||
|
master->DestroyPixmap(mpix);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pScrPriv->rrCrtcSetScanoutPixmap(crtc, spix);
|
||||||
|
if (ret == FALSE) {
|
||||||
|
ErrorF("failed to set shadow slave pixmap\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
crtc->scanout_pixmap = spix;
|
||||||
|
|
||||||
|
master->StartPixmapTracking(mscreenpix, spix, x, y);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bool
|
||||||
|
rrCheckPixmapBounding(ScreenPtr pScreen,
|
||||||
|
RRCrtcPtr rr_crtc, int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
RegionRec root_pixmap_region, total_region, new_crtc_region;
|
||||||
|
int i, c;
|
||||||
|
BoxRec newbox;
|
||||||
|
BoxPtr newsize;
|
||||||
|
ScreenPtr slave;
|
||||||
|
int new_width, new_height;
|
||||||
|
PixmapPtr screen_pixmap = pScreen->GetScreenPixmap(pScreen);
|
||||||
|
rrScrPriv(pScreen);
|
||||||
|
|
||||||
|
PixmapRegionInit(&root_pixmap_region, screen_pixmap);
|
||||||
|
RegionInit(&total_region, NULL, 0);
|
||||||
|
|
||||||
|
/* have to iterate all the crtcs of the attached gpu masters
|
||||||
|
and all their output slaves */
|
||||||
|
for (c = 0; c < pScrPriv->numCrtcs; c++) {
|
||||||
|
if (pScrPriv->crtcs[c] == rr_crtc) {
|
||||||
|
newbox.x1 = x;
|
||||||
|
newbox.x2 = x + w;
|
||||||
|
newbox.y1 = y;
|
||||||
|
newbox.y2 = y + h;
|
||||||
|
} else {
|
||||||
|
if (!pScrPriv->crtcs[c]->mode)
|
||||||
|
continue;
|
||||||
|
newbox.x1 = pScrPriv->crtcs[c]->x;
|
||||||
|
newbox.x2 = pScrPriv->crtcs[c]->x + pScrPriv->crtcs[c]->mode->mode.width;
|
||||||
|
newbox.y1 = pScrPriv->crtcs[c]->y;
|
||||||
|
newbox.y2 = pScrPriv->crtcs[c]->y + pScrPriv->crtcs[c]->mode->mode.height;
|
||||||
|
}
|
||||||
|
RegionInit(&new_crtc_region, &newbox, 1);
|
||||||
|
RegionUnion(&total_region, &total_region, &new_crtc_region);
|
||||||
|
}
|
||||||
|
|
||||||
|
xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) {
|
||||||
|
rrScrPriv(slave);
|
||||||
|
for (c = 0; c < pScrPriv->numCrtcs; c++)
|
||||||
|
if (pScrPriv->crtcs[c] == rr_crtc) {
|
||||||
|
newbox.x1 = x;
|
||||||
|
newbox.x2 = x + w;
|
||||||
|
newbox.y1 = y;
|
||||||
|
newbox.y2 = y + h;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!pScrPriv->crtcs[c]->mode)
|
||||||
|
continue;
|
||||||
|
newbox.x1 = pScrPriv->crtcs[c]->x;
|
||||||
|
newbox.x2 = pScrPriv->crtcs[c]->x + pScrPriv->crtcs[c]->mode->mode.width;
|
||||||
|
newbox.y1 = pScrPriv->crtcs[c]->y;
|
||||||
|
newbox.y2 = pScrPriv->crtcs[c]->y + pScrPriv->crtcs[c]->mode->mode.height;
|
||||||
|
}
|
||||||
|
RegionInit(&new_crtc_region, &newbox, 1);
|
||||||
|
RegionUnion(&total_region, &total_region, &new_crtc_region);
|
||||||
|
}
|
||||||
|
|
||||||
|
newsize = RegionExtents(&total_region);
|
||||||
|
new_width = newsize->x2 - newsize->x1;
|
||||||
|
new_height = newsize->y2 - newsize->y1;
|
||||||
|
|
||||||
|
if (new_width == screen_pixmap->drawable.width &&
|
||||||
|
new_height == screen_pixmap->drawable.height) {
|
||||||
|
ErrorF("adjust shatters %d %d\n", newsize->x1, newsize->x2);
|
||||||
|
} else {
|
||||||
|
int ret;
|
||||||
|
rrScrPriv(pScreen);
|
||||||
|
ret = pScrPriv->rrScreenSetSize(pScreen,
|
||||||
|
new_width, new_height, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set shatters TODO */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Request that the Crtc be reconfigured
|
* Request that the Crtc be reconfigured
|
||||||
*/
|
*/
|
||||||
|
@ -394,6 +542,26 @@ RRCrtcSet(RRCrtcPtr crtc,
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (pScreen->isGPU) {
|
||||||
|
ScreenPtr master = pScreen->current_master;
|
||||||
|
int width = 0, height = 0;
|
||||||
|
|
||||||
|
if (mode) {
|
||||||
|
width = mode->mode.width;
|
||||||
|
height = mode->mode.height;
|
||||||
|
}
|
||||||
|
ErrorF("have a master to look out for\n");
|
||||||
|
ret = rrCheckPixmapBounding(master, crtc,
|
||||||
|
x, y, width, height);
|
||||||
|
if (!ret)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (pScreen->current_master) {
|
||||||
|
ret = rrCreateSharedPixmap(crtc, width, height, x, y);
|
||||||
|
ErrorF("need to create shared pixmap %d", ret);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
#if RANDR_12_INTERFACE
|
#if RANDR_12_INTERFACE
|
||||||
if (pScrPriv->rrCrtcSet) {
|
if (pScrPriv->rrCrtcSet) {
|
||||||
ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y,
|
ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y,
|
||||||
|
@ -508,6 +676,9 @@ RRCrtcDestroyResource(pointer value, XID pid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (crtc->scanout_pixmap)
|
||||||
|
RRCrtcDetachScanoutPixmap(crtc);
|
||||||
free(crtc->gammaRed);
|
free(crtc->gammaRed);
|
||||||
if (crtc->mode)
|
if (crtc->mode)
|
||||||
RRModeDestroy(crtc->mode);
|
RRModeDestroy(crtc->mode);
|
||||||
|
|
Loading…
Reference in New Issue