summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2012-06-26 10:20:52 +0100
committerDave Airlie <airlied@redhat.com>2012-07-07 10:39:10 +0100
commit30298012162de7f76e8a4c7b0362e98703f80011 (patch)
tree22d31a9c13102a29ec55bbf4232f8f5a27953a9f
parent234022cfb3ad2a1b16ab7981ce69f9cd5ba0fbeb (diff)
dri2: add initial prime support. (v1.2)
This adds the initial prime support for dri2 offload. The main thing is when we get a connection from a prime client, we stored the information and mark all drawables from that client as prime. We then create all buffers for that drawable on the prime device dri2screen. Then DRI2UpdatePrime is provided which drivers can call to get a shared pixmap which they can use as the front buffer. The driver is then responsible for doing the back->front copy to the shared buffer. prime requires a compositing manager be run, but it handles the case where a window get un-redirected by allocating a new pixmap and pointing the crtc at it while the client is in that state. Currently prime can't handle pageflipping, so always does straight copy swap, v1.1: renumber on top of master. v1.2: fix auth on top of master. Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--glx/glxdri2.c2
-rw-r--r--hw/xfree86/dri2/dri2.c265
-rw-r--r--hw/xfree86/dri2/dri2.h25
-rw-r--r--hw/xfree86/dri2/dri2ext.c4
4 files changed, 267 insertions, 29 deletions
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index 1e99179d4..e0f4cf79e 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -931,3 +931,3 @@ __glXDRIscreenProbe(ScreenPtr pScreen)
if (!xf86LoaderCheckSymbol("DRI2Connect") ||
- !DRI2Connect(pScreen, DRI2DriverDRI,
+ !DRI2Connect(serverClient, pScreen, DRI2DriverDRI,
&screen->fd, &driverName, &deviceName)) {
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index d3b3c73f8..87158ff5c 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -47,3 +47,3 @@
#include "xf86VGAarbiter.h"
-
+#include "damage.h"
#include "xf86.h"
@@ -65,2 +65,13 @@ static DevPrivateKeyRec dri2PixmapPrivateKeyRec;
+static DevPrivateKeyRec dri2ClientPrivateKeyRec;
+
+#define dri2ClientPrivateKey (&dri2ClientPrivateKeyRec)
+
+#define dri2ClientPrivate(_pClient) (dixLookupPrivate(&(_pClient)->devPrivates, \
+ dri2ClientPrivateKey))
+
+typedef struct _DRI2Client {
+ int prime_id;
+} DRI2ClientRec, *DRI2ClientPtr;
+
static RESTYPE dri2DrawableRes;
@@ -89,2 +100,5 @@ typedef struct _DRI2Drawable {
Bool needInvalidate;
+ int prime_id;
+ PixmapPtr prime_slave_pixmap;
+ PixmapPtr redirectpixmap;
} DRI2DrawableRec, *DRI2DrawablePtr;
@@ -115,4 +129,10 @@ typedef struct _DRI2Screen {
ConfigNotifyProcPtr ConfigNotify;
+ DRI2CreateBuffer2ProcPtr CreateBuffer2;
+ DRI2DestroyBuffer2ProcPtr DestroyBuffer2;
+ DRI2CopyRegion2ProcPtr CopyRegion2;
} DRI2ScreenRec;
+static void
+destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, int prime_id);
+
static DRI2ScreenPtr
@@ -123,2 +143,29 @@ DRI2GetScreen(ScreenPtr pScreen)
+static ScreenPtr
+GetScreenPrime(ScreenPtr master, int prime_id)
+{
+ ScreenPtr slave;
+ int i;
+
+ if (prime_id == 0 || xorg_list_is_empty(&master->offload_slave_list)) {
+ return master;
+ }
+ i = 0;
+ xorg_list_for_each_entry(slave, &master->offload_slave_list, offload_head) {
+ if (i == (prime_id - 1))
+ break;
+ i++;
+ }
+ if (!slave)
+ return master;
+ return slave;
+}
+
+static DRI2ScreenPtr
+DRI2GetScreenPrime(ScreenPtr master, int prime_id)
+{
+ ScreenPtr slave = GetScreenPrime(master, prime_id);
+ return DRI2GetScreen(slave);
+}
+
static DRI2DrawablePtr
@@ -189,3 +236,4 @@ DRI2AllocateDrawable(DrawablePtr pDraw)
pPriv->needInvalidate = FALSE;
-
+ pPriv->redirectpixmap = NULL;
+ pPriv->prime_slave_pixmap = NULL;
if (pDraw->type == DRAWABLE_WINDOW) {
@@ -288,2 +336,3 @@ DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id,
DRI2DrawablePtr pPriv;
+ DRI2ClientPtr dri2_client = dri2ClientPrivate(client);
XID dri2_id;
@@ -297,2 +346,4 @@ DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id,
+ pPriv->prime_id = dri2_client->prime_id;
+
dri2_id = FakeClientID(client->index);
@@ -309,3 +360,2 @@ DRI2DrawableGone(pointer p, XID id)
DRI2DrawablePtr pPriv = p;
- DRI2ScreenPtr ds = pPriv->dri2_screen;
DRI2DrawableRefPtr ref, next;
@@ -349,3 +399,3 @@ DRI2DrawableGone(pointer p, XID id)
for (i = 0; i < pPriv->bufferCount; i++)
- (*ds->DestroyBuffer) (pDraw, pPriv->buffers[i]);
+ destroy_buffer(pDraw, pPriv->buffers[i], pPriv->prime_id);
@@ -354,2 +404,7 @@ DRI2DrawableGone(pointer p, XID id)
+ if (pPriv->redirectpixmap) {
+ (*pDraw->pScreen->ReplaceScanoutPixmap)(pDraw, pPriv->redirectpixmap, FALSE);
+ (*pDraw->pScreen->DestroyPixmap)(pPriv->redirectpixmap);
+ }
+
free(pPriv);
@@ -359,2 +414,33 @@ DRI2DrawableGone(pointer p, XID id)
+static DRI2BufferPtr
+create_buffer(DrawablePtr pDraw,
+ unsigned int attachment, unsigned int format)
+{
+ ScreenPtr primeScreen;
+ DRI2DrawablePtr pPriv;
+ DRI2ScreenPtr ds;
+ DRI2BufferPtr buffer;
+ pPriv = DRI2GetDrawable(pDraw);
+ primeScreen = GetScreenPrime(pDraw->pScreen, pPriv->prime_id);
+ ds = DRI2GetScreenPrime(pDraw->pScreen, pPriv->prime_id);
+ if (ds->CreateBuffer2)
+ buffer = (*ds->CreateBuffer2)(primeScreen, pDraw, attachment, format);
+ else
+ buffer = (*ds->CreateBuffer)(pDraw, attachment, format);
+ return buffer;
+}
+
+static void
+destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, int prime_id)
+{
+ ScreenPtr primeScreen;
+ DRI2ScreenPtr ds;
+ primeScreen = GetScreenPrime(pDraw->pScreen, prime_id);
+ ds = DRI2GetScreen(primeScreen);
+ if (ds->DestroyBuffer2)
+ (*ds->DestroyBuffer2)(primeScreen, pDraw, buffer);
+ else
+ (*ds->DestroyBuffer)(pDraw, buffer);
+}
+
static int
@@ -389,3 +475,3 @@ allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds,
|| !dimensions_match || (pPriv->buffers[old_buf]->format != format)) {
- *buffer = (*ds->CreateBuffer) (pDraw, attachment, format);
+ *buffer = create_buffer (pDraw, attachment, format);
pPriv->serialNumber = DRI2DrawableSerial(pDraw);
@@ -410,3 +496,2 @@ update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw,
{
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
int i;
@@ -416,3 +501,3 @@ update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw,
if (pPriv->buffers[i] != NULL) {
- (*ds->DestroyBuffer) (pDraw, pPriv->buffers[i]);
+ destroy_buffer(pDraw, pPriv->buffers[i], pPriv->prime_id);
}
@@ -436,4 +521,4 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
{
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
+ DRI2ScreenPtr ds;
DRI2BufferPtr *buffers;
@@ -454,2 +539,4 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
+ ds = DRI2GetScreen(pDraw->pScreen);
+
dimensions_match = (pDraw->width == pPriv->width)
@@ -558,3 +645,3 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
if (buffers[i] != NULL)
- (*ds->DestroyBuffer) (pDraw, buffers[i]);
+ destroy_buffer(pDraw, buffers[i], 0);
}
@@ -652,2 +739,110 @@ DRI2BlockClient(ClientPtr client, DrawablePtr pDraw)
+static inline PixmapPtr GetDrawablePixmap(DrawablePtr drawable)
+{
+ if (drawable->type == DRAWABLE_PIXMAP)
+ return (PixmapPtr)drawable;
+ else {
+ struct _Window *pWin = (struct _Window *)drawable;
+ return drawable->pScreen->GetWindowPixmap(pWin);
+ }
+}
+
+DrawablePtr DRI2UpdatePrime(DrawablePtr pDraw, DRI2BufferPtr pDest)
+{
+ DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
+ PixmapPtr spix;
+ PixmapPtr mpix = GetDrawablePixmap(pDraw);
+ ScreenPtr master, slave;
+ Bool ret;
+
+ master = mpix->drawable.pScreen;
+
+ if (pDraw->type == DRAWABLE_WINDOW) {
+ WindowPtr pWin = (WindowPtr)pDraw;
+ PixmapPtr pPixmap = pDraw->pScreen->GetWindowPixmap(pWin);
+
+ if (pDraw->pScreen->GetScreenPixmap(pDraw->pScreen) == pPixmap) {
+ if (pPriv->redirectpixmap &&
+ pPriv->redirectpixmap->drawable.width == pDraw->width &&
+ pPriv->redirectpixmap->drawable.height == pDraw->height &&
+ pPriv->redirectpixmap->drawable.depth == pDraw->depth) {
+ mpix = pPriv->redirectpixmap;
+ } else {
+ if (master->ReplaceScanoutPixmap) {
+ mpix = (*master->CreatePixmap)(master, pDraw->width, pDraw->height,
+ pDraw->depth, CREATE_PIXMAP_USAGE_SHARED);
+ if (!mpix)
+ return NULL;
+
+ ret = (*master->ReplaceScanoutPixmap)(pDraw, mpix, TRUE);
+ if (ret == FALSE) {
+ (*master->DestroyPixmap)(mpix);
+ return NULL;
+ }
+ pPriv->redirectpixmap = mpix;
+ } else
+ return NULL;
+ }
+ } else if (pPriv->redirectpixmap) {
+ (*master->ReplaceScanoutPixmap)(pDraw, pPriv->redirectpixmap, FALSE);
+ (*master->DestroyPixmap)(pPriv->redirectpixmap);
+ pPriv->redirectpixmap = NULL;
+ }
+ }
+
+ slave = GetScreenPrime(pDraw->pScreen, pPriv->prime_id);
+
+ /* check if the pixmap is still fine */
+ if (pPriv->prime_slave_pixmap) {
+ if (pPriv->prime_slave_pixmap->master_pixmap == mpix)
+ return &pPriv->prime_slave_pixmap->drawable;
+ else {
+ (*master->DestroyPixmap)(pPriv->prime_slave_pixmap->master_pixmap);
+ (*slave->DestroyPixmap)(pPriv->prime_slave_pixmap);
+ }
+ }
+
+ spix = PixmapShareToSlave(mpix, slave);
+ if (!spix)
+ return NULL;
+
+ pPriv->prime_slave_pixmap = spix;
+#ifdef COMPOSITE
+ spix->screen_x = mpix->screen_x;
+ spix->screen_y = mpix->screen_y;
+#endif
+ return &spix->drawable;
+}
+
+static void dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
+ DRI2BufferPtr pDest, DRI2BufferPtr pSrc)
+{
+ DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
+ DRI2ScreenPtr ds;
+ ScreenPtr primeScreen;
+
+ primeScreen = GetScreenPrime(pDraw->pScreen, pPriv->prime_id);
+ ds = DRI2GetScreen(primeScreen);
+
+ if (ds->CopyRegion2)
+ (*ds->CopyRegion2)(primeScreen, pDraw, pRegion, pDest, pSrc);
+ else
+ (*ds->CopyRegion) (pDraw, pRegion, pDest, pSrc);
+
+ /* cause damage to the box */
+ if (pPriv->prime_id) {
+ BoxRec box;
+ RegionRec region;
+ box.x1 = 0;
+ box.x2 = box.x1 + pDraw->width;
+ box.y1 = 0;
+ box.y2 = box.y1 + pDraw->height;
+ RegionInit(&region, &box, 1);
+ RegionTranslate(&region, pDraw->x, pDraw->y);
+ DamageRegionAppend(pDraw, &region);
+ DamageRegionProcessPending(pDraw);
+ RegionUninit(&region);
+ }
+}
+
int
@@ -656,3 +851,2 @@ DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
{
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
DRI2DrawablePtr pPriv;
@@ -676,3 +870,3 @@ DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
- (*ds->CopyRegion) (pDraw, pRegion, pDestBuffer, pSrcBuffer);
+ dri2_copy_region(pDraw, pRegion, pDestBuffer, pSrcBuffer);
@@ -881,3 +1075,3 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
/* Old DDX or no swap interval, just blit */
- if (!ds->ScheduleSwap || !pPriv->swap_interval) {
+ if (!ds->ScheduleSwap || !pPriv->swap_interval || pPriv->prime_id) {
BoxRec box;
@@ -893,3 +1087,3 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
- (*ds->CopyRegion) (pDraw, &region, pDestBuffer, pSrcBuffer);
+ dri2_copy_region(pDraw, &region, pDestBuffer, pSrcBuffer);
DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_BLIT_COMPLETE,
@@ -1093,3 +1287,4 @@ DRI2HasSwapControl(ScreenPtr pScreen)
Bool
-DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd,
+DRI2Connect(ClientPtr client, ScreenPtr pScreen,
+ unsigned int driverType, int *fd,
const char **driverName, const char **deviceName)
@@ -1097,2 +1292,4 @@ DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd,
DRI2ScreenPtr ds;
+ uint32_t prime_id = DRI2DriverPrimeId(driverType);
+ uint32_t driver_id = driverType & 0xffff;
@@ -1101,10 +1298,19 @@ DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd,
- ds = DRI2GetScreen(pScreen);
- if (ds == NULL || driverType >= ds->numDrivers ||
- !ds->driverNames[driverType])
+ ds = DRI2GetScreenPrime(pScreen, prime_id);
+ if (ds == NULL)
return FALSE;
- *fd = ds->fd;
- *driverName = ds->driverNames[driverType];
+ if (driver_id >= ds->numDrivers ||
+ !ds->driverNames[driver_id])
+ return FALSE;
+
+ *driverName = ds->driverNames[driver_id];
*deviceName = ds->deviceName;
+ *fd = ds->fd;
+
+ if (client) {
+ DRI2ClientPtr dri2_client;
+ dri2_client = dri2ClientPrivate(client);
+ dri2_client->prime_id = prime_id;
+ }
@@ -1124,9 +1330,15 @@ DRI2AuthMagic (ScreenPtr pScreen, uint32_t magic)
Bool
-DRI2Authenticate(ScreenPtr pScreen, uint32_t magic)
+DRI2Authenticate(ClientPtr client, ScreenPtr pScreen, uint32_t magic)
{
- DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
+ DRI2ScreenPtr ds;
+ DRI2ClientPtr dri2_client = dri2ClientPrivate(client);
+ ScreenPtr primescreen;
- if (ds == NULL || (*ds->AuthMagic) (pScreen, magic))
+ ds = DRI2GetScreenPrime(pScreen, dri2_client->prime_id);
+ if (ds == NULL)
return FALSE;
+ primescreen = GetScreenPrime(pScreen, dri2_client->prime_id);
+ if ((*ds->AuthMagic)(primescreen, magic))
+ return FALSE;
return TRUE;
@@ -1192,2 +1404,5 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
+ if (!dixRegisterPrivateKey(&dri2ClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(DRI2ClientRec)))
+ return FALSE;
+
ds = calloc(1, sizeof *ds);
@@ -1232,2 +1447,8 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
+ if (info->version >= 9) {
+ ds->CreateBuffer2 = info->CreateBuffer2;
+ ds->DestroyBuffer2 = info->DestroyBuffer2;
+ ds->CopyRegion2 = info->CopyRegion2;
+ }
+
/*
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index 4fd0fbc52..a59e680be 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -178,2 +178,14 @@ typedef Bool (*DRI2SwapLimitValidateProcPtr) (DrawablePtr pDraw,
+typedef DRI2BufferPtr(*DRI2CreateBuffer2ProcPtr) (ScreenPtr pScreen,
+ DrawablePtr pDraw,
+ unsigned int attachment,
+ unsigned int format);
+typedef void (*DRI2DestroyBuffer2ProcPtr) (ScreenPtr pScreen, DrawablePtr pDraw,
+ DRI2BufferPtr buffer);
+
+typedef void (*DRI2CopyRegion2ProcPtr) (ScreenPtr pScreen, DrawablePtr pDraw,
+ RegionPtr pRegion,
+ DRI2BufferPtr pDestBuffer,
+ DRI2BufferPtr pSrcBuffer);
+
/**
@@ -195,3 +207,3 @@ typedef int (*DRI2GetParamProcPtr) (ClientPtr client,
*/
-#define DRI2INFOREC_VERSION 8
+#define DRI2INFOREC_VERSION 9
@@ -230,3 +242,2 @@ typedef struct {
/* added in version 7 */
-
DRI2GetParamProcPtr GetParam;
@@ -238,2 +249,7 @@ typedef struct {
DRI2AuthMagic2ProcPtr AuthMagic2;
+
+ /* added in version 9 */
+ DRI2CreateBuffer2ProcPtr CreateBuffer2;
+ DRI2DestroyBuffer2ProcPtr DestroyBuffer2;
+ DRI2CopyRegion2ProcPtr CopyRegion2;
} DRI2InfoRec, *DRI2InfoPtr;
@@ -248,3 +264,3 @@ extern _X_EXPORT Bool DRI2HasSwapControl(ScreenPtr pScreen);
-extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen,
+extern _X_EXPORT Bool DRI2Connect(ClientPtr client, ScreenPtr pScreen,
unsigned int driverType,
@@ -254,3 +270,3 @@ extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen,
-extern _X_EXPORT Bool DRI2Authenticate(ScreenPtr pScreen, uint32_t magic);
+extern _X_EXPORT Bool DRI2Authenticate(ClientPtr client, ScreenPtr pScreen, uint32_t magic);
@@ -341,2 +357,3 @@ extern _X_EXPORT int DRI2GetParam(ClientPtr client,
+extern _X_EXPORT DrawablePtr DRI2UpdatePrime(DrawablePtr pDraw, DRI2BufferPtr pDest);
#endif
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index c6f5b4e11..3bc3ea74e 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -118,3 +118,3 @@ ProcDRI2Connect(ClientPtr client)
- if (!DRI2Connect(pDraw->pScreen,
+ if (!DRI2Connect(client, pDraw->pScreen,
stuff->driverType, &fd, &driverName, &deviceName))
@@ -151,3 +151,3 @@ ProcDRI2Authenticate(ClientPtr client)
rep.length = 0;
- rep.authenticated = DRI2Authenticate(pDraw->pScreen, stuff->magic);
+ rep.authenticated = DRI2Authenticate(client, pDraw->pScreen, stuff->magic);
WriteToClient(client, sizeof(xDRI2AuthenticateReply), &rep);