summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
@@ -929,7 +929,7 @@ __glXDRIscreenProbe(ScreenPtr pScreen)
return NULL;
if (!xf86LoaderCheckSymbol("DRI2Connect") ||
- !DRI2Connect(pScreen, DRI2DriverDRI,
+ !DRI2Connect(serverClient, pScreen, DRI2DriverDRI,
&screen->fd, &driverName, &deviceName)) {
LogMessage(X_INFO,
"AIGLX: Screen %d is not DRI2 capable\n", pScreen->myNum);
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
@@ -45,7 +45,7 @@
#include "dixstruct.h"
#include "dri2.h"
#include "xf86VGAarbiter.h"
-
+#include "damage.h"
#include "xf86.h"
CARD8 dri2_major; /* version of DRI2 supported by DDX */
@@ -63,6 +63,17 @@ static DevPrivateKeyRec dri2PixmapPrivateKeyRec;
#define dri2PixmapPrivateKey (&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;
typedef struct _DRI2Screen *DRI2ScreenPtr;
@@ -87,6 +98,9 @@ typedef struct _DRI2Drawable {
int swap_limit; /* for N-buffering */
unsigned long serialNumber;
Bool needInvalidate;
+ int prime_id;
+ PixmapPtr prime_slave_pixmap;
+ PixmapPtr redirectpixmap;
} DRI2DrawableRec, *DRI2DrawablePtr;
typedef struct _DRI2Screen {
@@ -113,14 +127,47 @@ typedef struct _DRI2Screen {
HandleExposuresProcPtr HandleExposures;
ConfigNotifyProcPtr ConfigNotify;
+ DRI2CreateBuffer2ProcPtr CreateBuffer2;
+ DRI2DestroyBuffer2ProcPtr DestroyBuffer2;
+ DRI2CopyRegion2ProcPtr CopyRegion2;
} DRI2ScreenRec;
+static void
+destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, int prime_id);
+
static DRI2ScreenPtr
DRI2GetScreen(ScreenPtr pScreen)
{
return dixLookupPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey);
}
+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
DRI2GetDrawable(DrawablePtr pDraw)
{
@@ -187,7 +234,8 @@ DRI2AllocateDrawable(DrawablePtr pDraw)
xorg_list_init(&pPriv->reference_list);
pPriv->serialNumber = DRI2DrawableSerial(pDraw);
pPriv->needInvalidate = FALSE;
-
+ pPriv->redirectpixmap = NULL;
+ pPriv->prime_slave_pixmap = NULL;
if (pDraw->type == DRAWABLE_WINDOW) {
pWin = (WindowPtr) pDraw;
dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
@@ -286,6 +334,7 @@ DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id,
DRI2InvalidateProcPtr invalidate, void *priv)
{
DRI2DrawablePtr pPriv;
+ DRI2ClientPtr dri2_client = dri2ClientPrivate(client);
XID dri2_id;
int rc;
@@ -295,6 +344,8 @@ DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id,
if (pPriv == NULL)
return BadAlloc;
+ pPriv->prime_id = dri2_client->prime_id;
+
dri2_id = FakeClientID(client->index);
rc = DRI2AddDrawableRef(pPriv, id, dri2_id, invalidate, priv);
if (rc != Success)
@@ -307,7 +358,6 @@ static int
DRI2DrawableGone(pointer p, XID id)
{
DRI2DrawablePtr pPriv = p;
- DRI2ScreenPtr ds = pPriv->dri2_screen;
DRI2DrawableRefPtr ref, next;
WindowPtr pWin;
PixmapPtr pPixmap;
@@ -347,16 +397,52 @@ DRI2DrawableGone(pointer p, XID id)
if (pPriv->buffers != NULL) {
for (i = 0; i < pPriv->bufferCount; i++)
- (*ds->DestroyBuffer) (pDraw, pPriv->buffers[i]);
+ destroy_buffer(pDraw, pPriv->buffers[i], pPriv->prime_id);
free(pPriv->buffers);
}
+ if (pPriv->redirectpixmap) {
+ (*pDraw->pScreen->ReplaceScanoutPixmap)(pDraw, pPriv->redirectpixmap, FALSE);
+ (*pDraw->pScreen->DestroyPixmap)(pPriv->redirectpixmap);
+ }
+
free(pPriv);
return Success;
}
+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
find_attachment(DRI2DrawablePtr pPriv, unsigned attachment)
{
@@ -387,7 +473,7 @@ allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds,
if ((old_buf < 0)
|| attachment == DRI2BufferFrontLeft
|| !dimensions_match || (pPriv->buffers[old_buf]->format != format)) {
- *buffer = (*ds->CreateBuffer) (pDraw, attachment, format);
+ *buffer = create_buffer (pDraw, attachment, format);
pPriv->serialNumber = DRI2DrawableSerial(pDraw);
return TRUE;
@@ -408,13 +494,12 @@ update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw,
DRI2BufferPtr * buffers, int out_count, int *width,
int *height)
{
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
int i;
if (pPriv->buffers != NULL) {
for (i = 0; i < pPriv->bufferCount; i++) {
if (pPriv->buffers[i] != NULL) {
- (*ds->DestroyBuffer) (pDraw, pPriv->buffers[i]);
+ destroy_buffer(pDraw, pPriv->buffers[i], pPriv->prime_id);
}
}
@@ -434,8 +519,8 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
unsigned int *attachments, int count, int *out_count,
int has_format)
{
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
+ DRI2ScreenPtr ds;
DRI2BufferPtr *buffers;
int need_real_front = 0;
int need_fake_front = 0;
@@ -452,6 +537,8 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
return NULL;
}
+ ds = DRI2GetScreen(pDraw->pScreen);
+
dimensions_match = (pDraw->width == pPriv->width)
&& (pDraw->height == pPriv->height)
&& (pPriv->serialNumber == DRI2DrawableSerial(pDraw));
@@ -556,7 +643,7 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
if (buffers) {
for (i = 0; i < count; i++) {
if (buffers[i] != NULL)
- (*ds->DestroyBuffer) (pDraw, buffers[i]);
+ destroy_buffer(pDraw, buffers[i], 0);
}
free(buffers);
@@ -650,11 +737,118 @@ DRI2BlockClient(ClientPtr client, DrawablePtr pDraw)
pPriv->blockedOnMsc = TRUE;
}
+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
DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
unsigned int dest, unsigned int src)
{
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
DRI2DrawablePtr pPriv;
DRI2BufferPtr pDestBuffer, pSrcBuffer;
int i;
@@ -674,7 +868,7 @@ DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
if (pSrcBuffer == NULL || pDestBuffer == NULL)
return BadValue;
- (*ds->CopyRegion) (pDraw, pRegion, pDestBuffer, pSrcBuffer);
+ dri2_copy_region(pDraw, pRegion, pDestBuffer, pSrcBuffer);
return Success;
}
@@ -879,7 +1073,7 @@ 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;
RegionRec region;
@@ -891,7 +1085,7 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
pPriv->swapsPending++;
- (*ds->CopyRegion) (pDraw, &region, pDestBuffer, pSrcBuffer);
+ dri2_copy_region(pDraw, &region, pDestBuffer, pSrcBuffer);
DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_BLIT_COMPLETE,
func, data);
return Success;
@@ -1091,22 +1285,34 @@ 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)
{
DRI2ScreenPtr ds;
+ uint32_t prime_id = DRI2DriverPrimeId(driverType);
+ uint32_t driver_id = driverType & 0xffff;
if (!dixPrivateKeyRegistered(dri2ScreenPrivateKey))
return FALSE;
- 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;
+ }
return TRUE;
}
@@ -1122,13 +1328,19 @@ 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;
}
@@ -1190,6 +1402,9 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
if (!dixRegisterPrivateKey(&dri2PixmapPrivateKeyRec, PRIVATE_PIXMAP, 0))
return FALSE;
+ if (!dixRegisterPrivateKey(&dri2ClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(DRI2ClientRec)))
+ return FALSE;
+
ds = calloc(1, sizeof *ds);
if (!ds)
return FALSE;
@@ -1230,6 +1445,12 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
cur_minor = 4;
}
+ if (info->version >= 9) {
+ ds->CreateBuffer2 = info->CreateBuffer2;
+ ds->DestroyBuffer2 = info->DestroyBuffer2;
+ ds->CopyRegion2 = info->CopyRegion2;
+ }
+
/*
* if the driver doesn't provide an AuthMagic function or the info struct
* version is too low, call through LegacyAuthMagic
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
@@ -176,6 +176,18 @@ typedef void (*DRI2InvalidateProcPtr) (DrawablePtr pDraw, void *data, XID id);
typedef Bool (*DRI2SwapLimitValidateProcPtr) (DrawablePtr pDraw,
int swap_limit);
+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);
+
/**
* \brief Get the value of a parameter.
*
@@ -193,7 +205,7 @@ typedef int (*DRI2GetParamProcPtr) (ClientPtr client,
/**
* Version of the DRI2InfoRec structure defined in this header
*/
-#define DRI2INFOREC_VERSION 8
+#define DRI2INFOREC_VERSION 9
typedef struct {
unsigned int version; /**< Version of this struct */
@@ -228,7 +240,6 @@ typedef struct {
DRI2SwapLimitValidateProcPtr SwapLimitValidate;
/* added in version 7 */
-
DRI2GetParamProcPtr GetParam;
/* added in version 8 */
@@ -236,6 +247,11 @@ typedef struct {
/* If this is NULL the AuthMagic callback is used */
/* If this is non-NULL the AuthMagic callback is ignored */
DRI2AuthMagic2ProcPtr AuthMagic2;
+
+ /* added in version 9 */
+ DRI2CreateBuffer2ProcPtr CreateBuffer2;
+ DRI2DestroyBuffer2ProcPtr DestroyBuffer2;
+ DRI2CopyRegion2ProcPtr CopyRegion2;
} DRI2InfoRec, *DRI2InfoPtr;
extern _X_EXPORT int DRI2EventBase;
@@ -246,13 +262,13 @@ extern _X_EXPORT void DRI2CloseScreen(ScreenPtr pScreen);
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,
int *fd,
const char **driverName,
const char **deviceName);
-extern _X_EXPORT Bool DRI2Authenticate(ScreenPtr pScreen, uint32_t magic);
+extern _X_EXPORT Bool DRI2Authenticate(ClientPtr client, ScreenPtr pScreen, uint32_t magic);
extern _X_EXPORT int DRI2CreateDrawable(ClientPtr client,
DrawablePtr pDraw,
@@ -339,4 +355,5 @@ extern _X_EXPORT int DRI2GetParam(ClientPtr client,
BOOL *is_param_recognized,
CARD64 *value);
+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
@@ -116,7 +116,7 @@ ProcDRI2Connect(ClientPtr client)
rep.driverNameLength = 0;
rep.deviceNameLength = 0;
- if (!DRI2Connect(pDraw->pScreen,
+ if (!DRI2Connect(client, pDraw->pScreen,
stuff->driverType, &fd, &driverName, &deviceName))
goto fail;
@@ -149,7 +149,7 @@ ProcDRI2Authenticate(ClientPtr client)
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 0;
- rep.authenticated = DRI2Authenticate(pDraw->pScreen, stuff->magic);
+ rep.authenticated = DRI2Authenticate(client, pDraw->pScreen, stuff->magic);
WriteToClient(client, sizeof(xDRI2AuthenticateReply), &rep);
return Success;