Add support for compositing

This commit is contained in:
Lauri Kasanen 2023-07-25 13:56:05 +00:00 committed by Ryan Kuba
parent 9450157af1
commit 0527c9f76e
2 changed files with 138 additions and 3 deletions

View File

@ -55,6 +55,15 @@ typedef struct gbm_pixmap gbm_pixmap;
static DevPrivateKeyRec dri3_pixmap_private_key; static DevPrivateKeyRec dri3_pixmap_private_key;
static struct timeval start; static struct timeval start;
#define MAX_TEXPIXMAPS 32
static PixmapPtr texpixmaps[MAX_TEXPIXMAPS];
static uint32_t num_texpixmaps;
static CARD32 update_texpixmaps(OsTimerPtr timer, CARD32 time, void *arg);
static OsTimerPtr texpixmaptimer;
void xvnc_sync_dri3_textures(void);
void xvnc_sync_dri3_pixmap(PixmapPtr pixmap);
void xvnc_init_dri3(void);
static int static int
@ -99,6 +108,29 @@ static gbm_pixmap *gbm_pixmap_get(PixmapPtr pixmap)
return dixLookupPrivate(&pixmap->devPrivates, &dri3_pixmap_private_key); return dixLookupPrivate(&pixmap->devPrivates, &dri3_pixmap_private_key);
} }
static void add_texpixmap(PixmapPtr pix)
{
uint32_t i;
for (i = 0; i < MAX_TEXPIXMAPS; i++) {
if (texpixmaps[i] == pix)
return;
}
for (i = 0; i < MAX_TEXPIXMAPS; i++) {
if (!texpixmaps[i]) {
texpixmaps[i] = pix;
pix->refcnt++;
num_texpixmaps++;
// start if not running
if (!texpixmaptimer)
texpixmaptimer = TimerSet(NULL, 0, 16, update_texpixmaps, NULL);
return;
}
}
ErrorF("Max number of texpixmaps reached\n");
}
static PixmapPtr static PixmapPtr
create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, CARD8 depth) create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, CARD8 depth)
{ {
@ -164,14 +196,33 @@ xvnc_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
uint64_t *modifier) uint64_t *modifier)
{ {
gbm_pixmap *gp = gbm_pixmap_get(pixmap); gbm_pixmap *gp = gbm_pixmap_get(pixmap);
if (!gp) {
gp = calloc(1, sizeof(gbm_pixmap));
if (!gp) if (!gp)
return 0; return 0;
gp->bo = gbm_bo_create(priv.gbm,
pixmap->drawable.width,
pixmap->drawable.height,
gbm_format_for_depth(pixmap->drawable.depth),
(pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED ?
GBM_BO_USE_LINEAR : 0) |
GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
if (!gp->bo) {
ErrorF("Failed to create bo\n");
return 0;
}
dri3_pixmap_set_private(pixmap, gp);
}
fds[0] = gbm_bo_get_fd(gp->bo); fds[0] = gbm_bo_get_fd(gp->bo);
strides[0] = gbm_bo_get_stride(gp->bo); strides[0] = gbm_bo_get_stride(gp->bo);
offsets[0] = 0; offsets[0] = 0;
*modifier = DRM_FORMAT_MOD_INVALID; *modifier = DRM_FORMAT_MOD_INVALID;
add_texpixmap(pixmap);
return 1; return 1;
} }
@ -219,12 +270,13 @@ void xvnc_sync_dri3_pixmap(PixmapPtr pixmap)
void *ptr; void *ptr;
uint32_t stride, w, h; uint32_t stride, w, h;
void *opaque = NULL; void *opaque = NULL;
gbm_pixmap *gp;
// We may not be running on hw if there's a compositor using PRESENT on llvmpipe // We may not be running on hw if there's a compositor using PRESENT on llvmpipe
if (!driNode) if (!driNode)
return; return;
gbm_pixmap *gp = gbm_pixmap_get(pixmap); gp = gbm_pixmap_get(pixmap);
if (!gp) { if (!gp) {
//ErrorF("Present tried to copy from a non-dri3 pixmap\n"); //ErrorF("Present tried to copy from a non-dri3 pixmap\n");
return; return;
@ -252,6 +304,69 @@ void xvnc_sync_dri3_pixmap(PixmapPtr pixmap)
gbm_bo_unmap(gp->bo, opaque); gbm_bo_unmap(gp->bo, opaque);
} }
void xvnc_sync_dri3_textures(void)
{
// Sync the tracked pixmaps into their textures (bos)
// This is a bit of an ugly solution, but we don't know
// when the pixmaps have changed nor when the textures are read.
//
// This is called both from the global damage report and the timer,
// to account for cases that do not use the damage report.
uint32_t i, y;
gbm_pixmap *gp;
uint8_t *src, *dst;
uint32_t srcstride, dststride;
void *opaque = NULL;
for (i = 0; i < MAX_TEXPIXMAPS; i++) {
if (!texpixmaps[i])
continue;
if (texpixmaps[i]->refcnt == 1) {
// We are the only user left, delete it
texpixmaps[i]->drawable.pScreen->DestroyPixmap(texpixmaps[i]);
texpixmaps[i] = NULL;
num_texpixmaps--;
continue;
}
gp = gbm_pixmap_get(texpixmaps[i]);
opaque = NULL;
dst = gbm_bo_map(gp->bo, 0, 0,
texpixmaps[i]->drawable.width,
texpixmaps[i]->drawable.height,
GBM_BO_TRANSFER_WRITE, &dststride, &opaque);
if (!dst) {
ErrorF("gbm map failed, errno %d\n", errno);
continue;
}
srcstride = texpixmaps[i]->devKind;
src = texpixmaps[i]->devPrivate.ptr;
for (y = 0; y < texpixmaps[i]->drawable.height; y++) {
memcpy(dst, src, srcstride);
dst += dststride;
src += srcstride;
}
gbm_bo_unmap(gp->bo, opaque);
}
}
static CARD32 update_texpixmaps(OsTimerPtr timer, CARD32 time, void *arg)
{
xvnc_sync_dri3_textures();
if (!num_texpixmaps) {
TimerFree(texpixmaptimer);
texpixmaptimer = NULL;
return 0;
}
return 16; // Reschedule next tick
}
void xvnc_init_dri3(void) void xvnc_init_dri3(void)
{ {
memset(&priv, 0, sizeof(priv)); memset(&priv, 0, sizeof(priv));

View File

@ -111,3 +111,23 @@ Index: xserver/mi/miinitext.c
gc = GetScratchGC(drawable->depth, screen); gc = GetScratchGC(drawable->depth, screen);
if (update) { if (update) {
ChangeGCVal changes[2]; ChangeGCVal changes[2];
--- xserver.orig/damageext/damageext.c 2019-02-26 21:28:50.000000000 +0200
+++ xserver/damageext/damageext.c 2023-03-21 12:52:58.411647186 +0200
@@ -87,6 +87,8 @@
*h = draw->height;
}
+void xvnc_sync_dri3_textures(void);
+
static void
DamageExtNotify(DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes)
{
@@ -97,6 +99,8 @@
damageGetGeometry(pDrawable, &x, &y, &w, &h);
+ xvnc_sync_dri3_textures();
+
UpdateCurrentTimeIf();
ev = (xDamageNotifyEvent) {
.type = DamageEventBase + XDamageNotify,