diff options
-rw-r--r-- | man/armsoc.man | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | src/armsoc_dri2.c | 278 | ||||
-rw-r--r-- | src/armsoc_driver.c | 24 | ||||
-rw-r--r-- | src/armsoc_driver.h | 20 | ||||
-rw-r--r-- | src/armsoc_dumb.c | 1 | ||||
-rw-r--r-- | src/armsoc_exa.c | 80 | ||||
-rw-r--r-- | src/drmmode_display.c | 12 | ||||
-rw-r--r-- | src/umplock/umplock_ioctl.h | 82 |
8 files changed, 427 insertions, 75 deletions
diff --git a/man/armsoc.man b/man/armsoc.man index 4a1b16a..d85c2fa 100644 --- a/man/armsoc.man +++ b/man/armsoc.man @@ -64,6 +64,11 @@ an error will be logged, and the -background none functionality will be disabled. .IP Default: NULL +.TP +.BI "Option \*qUMP_LOCK\*q \*q" boolean \*q +Use the umplock module for cross-process access synchronization. It should be only enabled for Mali400 +.IP +Default: Umplock is Disabled .SH DRM DEVICE SELECTION diff --git a/src/armsoc_dri2.c b/src/armsoc_dri2.c index 2e8571a..8e95ecb 100644..100755 --- a/src/armsoc_dri2.c +++ b/src/armsoc_dri2.c @@ -88,9 +88,8 @@ struct ARMSOCDRI2BufferRec { * overhead most of the time apart from when we switch from flipping * to blitting or vice versa. * - * We should bump the serial number of the drawable if canflip() returns - * something different to what is stored here, so that the DRI2 buffers - * will get re-allocated. + * If canflip() returns something different to what is stored here, + * the DRI2 buffers should be re-allocated. */ int previous_canflip; @@ -175,38 +174,17 @@ canexchange(DrawablePtr pDraw, struct armsoc_bo *src_bo, struct armsoc_bo *dst_b return ret; } -/** - * Create Buffer. - * - * Note that 'format' is used from the client side to specify the DRI buffer - * format, which could differ from the drawable format. For example, the - * drawable could be 32b RGB, but the DRI buffer some YUV format (video) or - * perhaps lower bit depth RGB (GL). The color conversion is handled when - * blitting to front buffer, and page-flipping (overlay or flipchain) can - * only be used if the display supports. - */ -static DRI2BufferPtr -ARMSOCDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment, - unsigned int format) +static Bool create_buffer(DrawablePtr pDraw, struct ARMSOCDRI2BufferRec *buf) { ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); - struct ARMSOCDRI2BufferRec *buf; struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); + DRI2BufferPtr buffer = DRIBUF(buf); PixmapPtr pPixmap = NULL; struct armsoc_bo *bo; int ret; - DEBUG_MSG("pDraw=%p, attachment=%d, format=%08x", - pDraw, attachment, format); - - buf = calloc(1, sizeof *buf); - if (!buf) { - ERROR_MSG("Couldn't allocate internal buffer structure"); - return NULL; - } - - if (attachment == DRI2BufferFrontLeft) { + if (buffer->attachment == DRI2BufferFrontLeft) { pPixmap = draw2pix(pDraw); pPixmap->refcnt++; } else { @@ -214,12 +192,12 @@ ARMSOCDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment, } if (!pPixmap) { - assert(attachment != DRI2BufferFrontLeft); + assert(buffer->attachment != DRI2BufferFrontLeft); ERROR_MSG("Failed to create back buffer for window"); goto fail; } - if (attachment == DRI2BufferBackLeft && pARMSOC->driNumBufs > 2) { + if (buffer->attachment == DRI2BufferBackLeft && pARMSOC->driNumBufs > 2) { buf->pPixmaps = calloc(pARMSOC->driNumBufs-1, sizeof(PixmapPtr)); buf->numPixmaps = pARMSOC->driNumBufs-1; @@ -243,10 +221,8 @@ ARMSOCDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment, goto fail; } - DRIBUF(buf)->attachment = attachment; DRIBUF(buf)->pitch = exaGetPixmapPitch(pPixmap); DRIBUF(buf)->cpp = pPixmap->drawable.bitsPerPixel / 8; - DRIBUF(buf)->format = format; DRIBUF(buf)->flags = 0; buf->refcnt = 1; buf->previous_canflip = canflip(pDraw); @@ -257,7 +233,7 @@ ARMSOCDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment, goto fail; } - if (canflip(pDraw) && attachment != DRI2BufferFrontLeft) { + if (canflip(pDraw) && buffer->attachment != DRI2BufferFrontLeft) { /* Create an fb around this buffer. This will fail and we will * fall back to blitting if the display controller hardware * cannot scan out this buffer (for example, if it doesn't @@ -277,44 +253,35 @@ ARMSOCDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment, #endif /* DRI2INFOREC_VERSION >= 6 */ } + DRI2_BUFFER_SET_FB(DRIBUF(buf)->flags, armsoc_bo_get_fb(bo) > 0 ? 1 : 0); + DRI2_BUFFER_SET_REUSED(DRIBUF(buf)->flags, 0); /* Register Pixmap as having a buffer that can be accessed externally, * so needs synchronised access */ ARMSOCRegisterExternalAccess(pPixmap); - return DRIBUF(buf); + return TRUE; fail: if (pPixmap != NULL) { - if (attachment != DRI2BufferFrontLeft) + if (buffer->attachment != DRI2BufferFrontLeft) pScreen->DestroyPixmap(pPixmap); else pPixmap->refcnt--; } - free(buf->pPixmaps); - free(buf); - return NULL; + return FALSE; } -/** - * Destroy Buffer - */ -static void -ARMSOCDRI2DestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer) +static Bool destroy_buffer(DrawablePtr pDraw, struct ARMSOCDRI2BufferRec *buf) { - struct ARMSOCDRI2BufferRec *buf = ARMSOCBUF(buffer); - /* Note: pDraw may already be deleted, so use the pPixmap here - * instead (since it is at least refcntd) - */ ScreenPtr pScreen = buf->pPixmaps[0]->drawable.pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); + DRI2BufferPtr buffer = DRIBUF(buf); int numBuffers, i; if (--buf->refcnt > 0) - return; - - DEBUG_MSG("pDraw=%p, DRIbuffer=%p", pDraw, buffer); + return FALSE; if (buffer->attachment == DRI2BufferBackLeft) { assert(pARMSOC->driNumBufs > 1); @@ -327,8 +294,74 @@ ARMSOCDRI2DestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer) pScreen->DestroyPixmap(buf->pPixmaps[i]); } - free(buf->pPixmaps); - free(buf); + return TRUE; +} + +/** + * Create Buffer. + * + * Note that 'format' is used from the client side to specify the DRI buffer + * format, which could differ from the drawable format. For example, the + * drawable could be 32b RGB, but the DRI buffer some YUV format (video) or + * perhaps lower bit depth RGB (GL). The color conversion is handled when + * blitting to front buffer, and page-flipping (overlay or flipchain) can + * only be used if the display supports. + */ +static DRI2BufferPtr +ARMSOCDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment, + unsigned int format) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + struct ARMSOCDRI2BufferRec *buf; + + DEBUG_MSG("pDraw=%p, attachment=%d, format=%08x", + pDraw, attachment, format); + + buf = calloc(1, sizeof *buf); + if (!buf) { + ERROR_MSG("Couldn't allocate internal buffer structure"); + return NULL; + } + + DRIBUF(buf)->attachment = attachment; + DRIBUF(buf)->format = format; + + if (!create_buffer(pDraw, buf)) { + free(buf); + return NULL; + } + + return DRIBUF(buf); +} + +/** + * Destroy Buffer + */ +static void +ARMSOCDRI2DestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer) +{ + struct ARMSOCDRI2BufferRec *buf = ARMSOCBUF(buffer); + ScreenPtr pScreen; + ScrnInfoPtr pScrn; + /* Note: pDraw may already be deleted, so use the pPixmap here + * instead (since it is at least refcntd) + */ + if (NULL == buf->pPixmaps || NULL == buf->pPixmaps[0]) { + if (--buf->refcnt == 0) + free(buf); + return; + } + + pScreen = buf->pPixmaps[0]->drawable.pScreen; + pScrn = xf86ScreenToScrn(pScreen); + + DEBUG_MSG("pDraw=%p, DRIbuffer=%p", pDraw, buffer); + + if (destroy_buffer(pDraw, buf)) { + free(buf->pPixmaps); + free(buf); + } } static void @@ -467,6 +500,12 @@ static const char * const swap_names[] = { [DRI2_FLIP_COMPLETE] = "flip," }; +struct ARMSOCDRIVBlankCmd { + int type; + ClientPtr client; + DrawablePtr pDraw; +}; + static Bool allocNextBuffer(DrawablePtr pDraw, PixmapPtr *ppPixmap, uint32_t *name) { ScreenPtr pScreen = pDraw->pScreen; @@ -498,10 +537,8 @@ static Bool allocNextBuffer(DrawablePtr pDraw, PixmapPtr *ppPixmap, goto error; } - if (!armsoc_bo_get_fb(bo)) { + if (canflip(pDraw) && !armsoc_bo_get_fb(bo)) { ret = armsoc_bo_add_fb(bo); - /* Should always be able to add fb, as we only add more buffers - * when flipping*/ if (ret) { ERROR_MSG( "Could not add framebuffer to additional back buffer"); @@ -718,13 +755,23 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw, struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); struct ARMSOCDRI2BufferRec *src = ARMSOCBUF(pSrcBuffer); struct ARMSOCDRI2BufferRec *dst = ARMSOCBUF(pDstBuffer); +#if DRI2INFOREC_VERSION < 6 + int new_canflip; +#endif struct ARMSOCDRISwapCmd *cmd; struct armsoc_bo *src_bo, *dst_bo; int src_fb_id, dst_fb_id; - int new_canflip, ret, do_flip; + int ret, do_flip; unsigned int idx; RegionRec region; - PixmapPtr pDstPixmap = draw2pix(dri2draw(pDraw, pDstBuffer)); + PixmapPtr pDstPixmap = NULL; + + if (NULL == src->pPixmaps || NULL == src->pPixmaps[src->currentPixmap] + || NULL == dst->pPixmaps || NULL == dst->pPixmaps[dst->currentPixmap]) { + return FALSE; + } + + pDstPixmap = draw2pix(dri2draw(pDraw, pDstBuffer)); cmd = calloc(1, sizeof(*cmd)); if (!cmd) @@ -773,6 +820,7 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw, DEBUG_MSG("SWAP %d SCHEDULED : %d -> %d ", cmd->swap_id, pSrcBuffer->attachment, pDstBuffer->attachment); +#if DRI2INFOREC_VERSION < 6 new_canflip = canflip(pDraw); if ((src->previous_canflip != new_canflip) || (dst->previous_canflip != new_canflip)) { @@ -792,6 +840,7 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw, src->previous_canflip = new_canflip; dst->previous_canflip = new_canflip; +#endif do_flip = src_fb_id && dst_fb_id && canflip(pDraw); @@ -904,6 +953,13 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw, return TRUE; } +void ARMSOCDRI2VBlankHandler(unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + struct ARMSOCDRIVBlankCmd *cmd = (struct ARMSOCDRIVBlankCmd *)user_data; + DRI2WaitMSCComplete(cmd->client, cmd->pDraw, sequence, tv_sec, tv_usec); + free(cmd); +} + /** * Request a DRM event when the requested conditions will be satisfied. * @@ -916,10 +972,103 @@ ARMSOCDRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr pDraw, { ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); + struct ARMSOCDRIVBlankCmd *cmd = NULL; + drmVBlank vbl = { .request = { + .type = DRM_VBLANK_RELATIVE, + .sequence = 0, + } }; + int ret; + CARD64 current_msc; - ERROR_MSG("not implemented"); - return FALSE; + if (!pARMSOC->drmmode_interface->vblank_query_supported) + return FALSE; + + ret = drmWaitVBlank(pARMSOC->drmFD, &vbl); + if (ret) { + ERROR_MSG("get vblank counter failed: %s", strerror(errno)); + return FALSE; + } + current_msc = vbl.reply.sequence; + + if (current_msc >= target_msc) { + DRI2WaitMSCComplete(client, pDraw, current_msc, 0, 0); + return TRUE; + } + + cmd = calloc(1, sizeof(*cmd)); + if (!cmd) + return FALSE; + + cmd->type = 0; + cmd->client = client; + cmd->pDraw = pDraw; + + vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; + vbl.request.sequence = target_msc; + vbl.request.signal = (unsigned long)cmd; + ret = drmWaitVBlank(pARMSOC->drmFD, &vbl); + if (ret) { + ERROR_MSG("get vblank counter failed: %s", strerror(errno)); + return FALSE; + } + DRI2BlockClient(client, pDraw); + + return TRUE; } +#if DRI2INFOREC_VERSION >= 6 +/** + * Called by DRI2 to reuse a buffer which is created earlier. + */ +static void +ARMSOCDRI2ReuseBufferNotify(DrawablePtr pDraw, DRI2BufferPtr buffer) +{ + int new_canflip, ret, fb_id; + struct armsoc_bo *bo; + struct ARMSOCDRI2BufferRec *buf = ARMSOCBUF(buffer); + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + + DRI2_BUFFER_SET_REUSED(buffer->flags, 1); + if (DRI2BufferBackLeft != buffer->attachment) { + return; + } + + new_canflip = canflip(pDraw); + if (buf->previous_canflip == new_canflip) { + return; + } + + if (destroy_buffer(pDraw, buf)) { + free(buf->pPixmaps); + buf->pPixmaps = NULL; + if (!create_buffer(pDraw, buf)) { + ERROR_MSG("Failed to create buffer"); + } + } else { + bo = boFromBuffer(buffer); + fb_id = armsoc_bo_get_fb(bo); + if (buf->previous_canflip == FALSE && new_canflip == TRUE && fb_id == 0) { + ret = armsoc_bo_add_fb(bo); + if (ret) { + WARNING_MSG("Falling back to blitting a flippable window"); + } else { + DRI2_BUFFER_SET_FB(buffer->flags, 1); + } + buf->previous_canflip = new_canflip; + } else if (buf->previous_canflip == TRUE && new_canflip == FALSE && fb_id) { + ret = armsoc_bo_rm_fb(bo); + if (ret) { + ERROR_MSG("Could not remove fb for a flippable to non-flippable window"); + } else { + DRI2_BUFFER_SET_FB(buffer->flags, 0); + } + buf->previous_canflip = new_canflip; + } + } +} +#endif + /** * The DRI2 ScreenInit() function.. register our handler fxns w/ DRI2 core @@ -929,6 +1078,12 @@ ARMSOCDRI2ScreenInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); + drmVBlank vbl = { .request = { + .type = DRM_VBLANK_RELATIVE, + .sequence = 0, + } }; + int ret; + DRI2InfoRec info = { #if DRI2INFOREC_VERSION >= 6 .version = 6, @@ -946,6 +1101,7 @@ ARMSOCDRI2ScreenInit(ScreenPtr pScreen) .GetMSC = ARMSOCDRI2GetMSC, .AuthMagic = drmAuthMagic, #if DRI2INFOREC_VERSION >= 6 + .ReuseBufferNotify = ARMSOCDRI2ReuseBufferNotify, .SwapLimitValidate = ARMSOCDRI2SwapLimitValidate, #endif }; @@ -990,6 +1146,12 @@ ARMSOCDRI2ScreenInit(ScreenPtr pScreen) INFO_MSG("Setting swap chain size: %d ", pARMSOC->swap_chain_size); + ret = drmWaitVBlank(pARMSOC->drmFD, &vbl); + if (ret) + pARMSOC->drmmode_interface->vblank_query_supported = 0; + else + pARMSOC->drmmode_interface->vblank_query_supported = 1; + return DRI2ScreenInit(pScreen, &info); } diff --git a/src/armsoc_driver.c b/src/armsoc_driver.c index f0764ef..cbb982b 100644 --- a/src/armsoc_driver.c +++ b/src/armsoc_driver.c @@ -108,6 +108,7 @@ enum { OPTION_DRIVERNAME, OPTION_DRI_NUM_BUF, OPTION_INIT_FROM_FBDEV, + OPTION_UMP_LOCK, }; /** Supported options. */ @@ -119,6 +120,7 @@ static const OptionInfoRec ARMSOCOptions[] = { { OPTION_DRIVERNAME, "DriverName", OPTV_STRING, {0}, FALSE }, { OPTION_DRI_NUM_BUF, "DRI2MaxBuffers", OPTV_INTEGER, {-1}, FALSE }, { OPTION_INIT_FROM_FBDEV, "InitFromFBDev", OPTV_STRING, {0}, FALSE }, + { OPTION_UMP_LOCK, "UMP_LOCK", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -856,6 +858,10 @@ ARMSOCPreInit(ScrnInfoPtr pScrn, int flags) OPTION_NO_FLIP, FALSE); INFO_MSG("Buffer Flipping is %s", pARMSOC->NoFlip ? "Disabled" : "Enabled"); + pARMSOC->useUmplock = xf86ReturnOptValBool(pARMSOC->pOptionInfo, + OPTION_UMP_LOCK, FALSE); + INFO_MSG("umplock is %s", + pARMSOC->useUmplock ? "Disabled" : "Enabled"); /* * Select the video modes: @@ -1127,6 +1133,15 @@ ARMSOCScreenInit(SCREEN_INIT_ARGS_DECL) wrap(pARMSOC, pScreen, BlockHandler, ARMSOCBlockHandler); drmmode_screen_init(pScrn); + if (pARMSOC->useUmplock) { + pARMSOC->lockFD = open("/dev/umplock", O_RDWR); + + if (-1 == pARMSOC->lockFD) + ERROR_MSG("Failed to open umplock device!"); + } else { + pARMSOC->lockFD = -1; + } + TRACE_EXIT(); return TRUE; @@ -1241,6 +1256,11 @@ ARMSOCCloseScreen(CLOSE_SCREEN_ARGS_DECL) pScrn->vtSema = FALSE; + if (-1 != pARMSOC->lockFD) { + close(pARMSOC->lockFD); + pARMSOC->lockFD = -1; + } + TRACE_EXIT(); return ret; @@ -1323,7 +1343,7 @@ ARMSOCEnterVT(VT_FUNC_ARGS_DECL) TRACE_ENTER(); for (i = 1; i < currentMaxClients; i++) { - if (clients[i]) + if (clients[i] && !clients[i]->clientGone) AttendClient(clients[i]); } @@ -1358,7 +1378,7 @@ ARMSOCLeaveVT(VT_FUNC_ARGS_DECL) TRACE_ENTER(); for (i = 1; i < currentMaxClients; i++) { - if (clients[i]) + if (clients[i] && !clients[i]->clientGone) IgnoreClient(clients[i]); } diff --git a/src/armsoc_driver.h b/src/armsoc_driver.h index 4621dcc..ef2836f 100644 --- a/src/armsoc_driver.h +++ b/src/armsoc_driver.h @@ -105,6 +105,21 @@ extern _X_EXPORT Bool armsocDebug; ##__VA_ARGS__); \ } while (0) +#define DRI2_BUFFER_FB_MASK 0x02 /* FB: 1, non-FB: 0 */ +#define DRI2_BUFFER_MAPPED_MASK 0x04 /* mapped: 1, not-mapped: 0 */ +#define DRI2_BUFFER_REUSED_MASK 0x08 /* re-used: 1, re-created: 0 */ +#define DRI2_BUFFER_AGE_MASK 0x70 /* buffer age */ +#define DRI2_BUFFER_FLAG_MASK 0x7f /* dri2 buffer flag mask */ + +#define DRI2_BUFFER_GET_FB(flag) ((flag) & DRI2_BUFFER_FB_MASK) ? 1 : 0 +#define DRI2_BUFFER_SET_FB(flag, fb) (flag) |= (((fb) << 1) & DRI2_BUFFER_FB_MASK); +#define DRI2_BUFFER_GET_MAPPED(flag) ((flag) & DRI2_BUFFER_MAPPED_MASK) ? 1 : 0 +#define DRI2_BUFFER_SET_MAPPED(flag, mapped) (flag) |= (((mapped) << 2) & DRI2_BUFFER_MAPPED_MASK); +#define DRI2_BUFFER_GET_REUSED(flag) ((flag) & DRI2_BUFFER_REUSED_MASK) ? 1 : 0 +#define DRI2_BUFFER_SET_REUSED(flag, reused) (flag) |= (((reused) << 3) & DRI2_BUFFER_REUSED_MASK); +#define DRI2_BUFFER_GET_AGE(flag) ((flag) & DRI2_BUFFER_AGE_MASK) >> 4 +#define DRI2_BUFFER_SET_AGE(flag, age) (flag) |= (((age) << 4) & DRI2_BUFFER_AGE_MASK); + /** The driver's Screen-specific, "private" data structure. */ struct ARMSOCRec { /** @@ -151,6 +166,10 @@ struct ARMSOCRec { /* Identify which CRTC to use. -1 uses all CRTCs */ int crtcNum; + Bool useUmplock; + /* File descriptor of the umplock*/ + int lockFD; + /* The Swap Chain stores the pending swap operations */ struct ARMSOCDRISwapCmd **swap_chain; @@ -220,6 +239,7 @@ Bool ARMSOCDRI2ScreenInit(ScreenPtr pScreen); void ARMSOCDRI2CloseScreen(ScreenPtr pScreen); void ARMSOCDRI2SwapComplete(struct ARMSOCDRISwapCmd *cmd); void ARMSOCDRI2ResizeSwapChain(ScrnInfoPtr pScrn, struct armsoc_bo *old_bo, struct armsoc_bo *resized_bo); +void ARMSOCDRI2VBlankHandler(unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data); /** * DRI2 util functions.. diff --git a/src/armsoc_dumb.c b/src/armsoc_dumb.c index 47027b7..7e6dbd9 100644 --- a/src/armsoc_dumb.c +++ b/src/armsoc_dumb.c @@ -32,6 +32,7 @@ #include <errno.h> #include <unistd.h> +#include <xorg-server.h> #include <xf86.h> #include <xf86drm.h> #include <xf86drmMode.h> diff --git a/src/armsoc_exa.c b/src/armsoc_exa.c index 87f28e1..a310727 100644 --- a/src/armsoc_exa.c +++ b/src/armsoc_exa.c @@ -31,6 +31,9 @@ #include "armsoc_exa.h" #include "armsoc_driver.h" +#include "umplock/umplock_ioctl.h" +#include <sys/ioctl.h> +#include <unistd.h> /* keep this here, instead of static-inline so submodule doesn't * need to know layout of ARMSOCRec. @@ -324,6 +327,12 @@ static inline enum armsoc_gem_op idx2op(int index) _X_EXPORT Bool ARMSOCPrepareAccess(PixmapPtr pPixmap, int index) { + ScreenPtr pScreen = pPixmap->drawable.pScreen; + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); + uint32_t dmabuf_name = 0; + _lock_item_s item; + int ret; struct ARMSOCPixmapPrivRec *priv = exaGetPixmapDriverPrivate(pPixmap); pPixmap->devPrivate.ptr = armsoc_bo_map(priv->bo); @@ -344,13 +353,39 @@ ARMSOCPrepareAccess(PixmapPtr pPixmap, int index) } } - if (armsoc_bo_cpu_prep(priv->bo, idx2op(index))) { - xf86DrvMsg(-1, X_ERROR, - "%s: armsoc_bo_cpu_prep failed - unable to synchronise access.\n", - __func__); - return FALSE; - } + if (-1 != pARMSOC->lockFD) { + ret = armsoc_bo_get_name(priv->bo, &dmabuf_name); + + if (ret) { + ERROR_MSG("could not get buffer name"); + return FALSE; + } + + item.secure_id = dmabuf_name; + item.usage = _LOCK_ACCESS_CPU_WRITE; + if (ioctl(pARMSOC->lockFD, LOCK_IOCTL_CREATE, &item) < 0) { + ERROR_MSG("Unable to create lock item\n"); + return FALSE; + } + if (ioctl(pARMSOC->lockFD, LOCK_IOCTL_PROCESS, &item) < 0) { + int max_retries = 5; + ERROR_MSG("Unable to process lock item with ID 0x%x - throttling\n", item.secure_id); + while ((ioctl(pARMSOC->lockFD, LOCK_IOCTL_PROCESS, &item) < 0) && max_retries) { + usleep(2000); + max_retries--; + } + if (max_retries == 0) + ERROR_MSG("Warning: Max retries == 0\n"); + } + } else { + if (armsoc_bo_cpu_prep(priv->bo, idx2op(index))) { + xf86DrvMsg(-1, X_ERROR, + "%s: armsoc_bo_cpu_prep failed - unable to synchronise access.\n", + __func__); + return FALSE; + } + } return TRUE; } @@ -367,15 +402,32 @@ ARMSOCPrepareAccess(PixmapPtr pPixmap, int index) _X_EXPORT void ARMSOCFinishAccess(PixmapPtr pPixmap, int index) { + ScreenPtr pScreen = pPixmap->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; struct ARMSOCPixmapPrivRec *priv = exaGetPixmapDriverPrivate(pPixmap); - - pPixmap->devPrivate.ptr = NULL; - - /* NOTE: can we use EXA migration module to track which parts of the - * buffer was accessed by sw, and pass that info down to kernel to - * do a more precise cache flush.. - */ - armsoc_bo_cpu_fini(priv->bo, idx2op(index)); + struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); + if (-1 != pARMSOC->lockFD){ + uint32_t dmabuf_name = 0; + _lock_item_s item; + int ret; + + pPixmap->devPrivate.ptr = NULL; + ret = armsoc_bo_get_name(priv->bo, &dmabuf_name); + if (ret) { + ERROR_MSG("could not get buffer name"); + return ; + } + item.secure_id = dmabuf_name; + item.usage = _LOCK_ACCESS_CPU_WRITE; + ioctl(pARMSOC->lockFD, LOCK_IOCTL_RELEASE, &item); + }else{ + /* NOTE: can we use EXA migration module to track which parts of the + * buffer was accessed by sw, and pass that info down to kernel to + * do a more precise cache flush.. + */ + pPixmap->devPrivate.ptr = NULL; + armsoc_bo_cpu_fini(priv->bo, idx2op(index)); + } } /** diff --git a/src/drmmode_display.c b/src/drmmode_display.c index bfa1905..80cf562 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -417,7 +417,7 @@ cleanup: if (output_ids) free(output_ids); - if (!ret && !drmmode_crtc->last_good_mode) { + if (!ret && drmmode_crtc->last_good_mode) { /* If there was a problem, restore the last good mode: */ crtc->x = drmmode_crtc->last_good_x; crtc->y = drmmode_crtc->last_good_y; @@ -965,6 +965,8 @@ drmmode_output_get_modes(xf86OutputPtr output) drmmode_output->edid_blob->data); if (ddc_mon) { + if (drmmode_output->edid_blob->length > 128) + ddc_mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA; xf86OutputSetEDID(output, ddc_mon); xf86SetDDCproperties(pScrn, ddc_mon); } @@ -1733,9 +1735,17 @@ page_flip_handler(int fd, unsigned int sequence, unsigned int tv_sec, ARMSOCDRI2SwapComplete(user_data); } +static void +vblank_handler(int fd, unsigned int sequence, unsigned int tv_sec, + unsigned int tv_usec, void *user_data) +{ + ARMSOCDRI2VBlankHandler(sequence, tv_sec, tv_usec, user_data); +} + static drmEventContext event_context = { .version = DRM_EVENT_CONTEXT_VERSION, .page_flip_handler = page_flip_handler, + .vblank_handler = vblank_handler, }; int diff --git a/src/umplock/umplock_ioctl.h b/src/umplock/umplock_ioctl.h new file mode 100644 index 0000000..4be19a0 --- /dev/null +++ b/src/umplock/umplock_ioctl.h @@ -0,0 +1,82 @@ +/* + * Copyright © 2013 ARM Limited. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef __UMPLOCK_IOCTL_H__ +#define __UMPLOCK_IOCTL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <linux/types.h> +#include <linux/ioctl.h> + +#ifndef __user +#define __user +#endif + + +/** + * @file umplock_ioctl.h + * This file describes the interface needed to use the Linux device driver. + * The interface is used by the userpace Mali DDK. + */ + +typedef enum +{ + _LOCK_ACCESS_RENDERABLE = 1, + _LOCK_ACCESS_TEXTURE, + _LOCK_ACCESS_CPU_WRITE, + _LOCK_ACCESS_CPU_READ, +} _lock_access_usage; + +typedef struct _lock_item_s +{ + unsigned int secure_id; + _lock_access_usage usage; +} _lock_item_s; + + +#define LOCK_IOCTL_GROUP 0x91 + +#define _LOCK_IOCTL_CREATE_CMD 0 /* create kernel lock item */ +#define _LOCK_IOCTL_PROCESS_CMD 1 /* process kernel lock item */ +#define _LOCK_IOCTL_RELEASE_CMD 2 /* release kernel lock item */ +#define _LOCK_IOCTL_ZAP_CMD 3 /* clean up all kernel lock items */ +#define _LOCK_IOCTL_DUMP_CMD 4 /* dump all the items */ + +#define LOCK_IOCTL_MAX_CMDS 5 + +#define LOCK_IOCTL_CREATE _IOW( LOCK_IOCTL_GROUP, _LOCK_IOCTL_CREATE_CMD, _lock_item_s ) +#define LOCK_IOCTL_PROCESS _IOW( LOCK_IOCTL_GROUP, _LOCK_IOCTL_PROCESS_CMD, _lock_item_s ) +#define LOCK_IOCTL_RELEASE _IOW( LOCK_IOCTL_GROUP, _LOCK_IOCTL_RELEASE_CMD, _lock_item_s ) +#define LOCK_IOCTL_ZAP _IO ( LOCK_IOCTL_GROUP, _LOCK_IOCTL_ZAP_CMD ) +#define LOCK_IOCTL_DUMP _IO ( LOCK_IOCTL_GROUP, _LOCK_IOCTL_DUMP_CMD ) + +#ifdef __cplusplus +} +#endif + +#endif /* __UMPLOCK_IOCTL_H__ */ + |