diff options
-rw-r--r-- | glx/glxdri2.c | 2 | ||||
-rw-r--r-- | hw/xfree86/dri2/dri2.c | 265 | ||||
-rw-r--r-- | hw/xfree86/dri2/dri2.h | 25 | ||||
-rw-r--r-- | hw/xfree86/dri2/dri2ext.c | 4 |
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(®ion, &box, 1); + RegionTranslate(®ion, pDraw->x, pDraw->y); + DamageRegionAppend(pDraw, ®ion); + DamageRegionProcessPending(pDraw); + RegionUninit(®ion); + } +} + 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, ®ion, pDestBuffer, pSrcBuffer); + dri2_copy_region(pDraw, ®ion, 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; |