summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/armsoc.man5
-rwxr-xr-x[-rw-r--r--]src/armsoc_dri2.c278
-rw-r--r--src/armsoc_driver.c24
-rw-r--r--src/armsoc_driver.h20
-rw-r--r--src/armsoc_dumb.c1
-rw-r--r--src/armsoc_exa.c80
-rw-r--r--src/drmmode_display.c12
-rw-r--r--src/umplock/umplock_ioctl.h82
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__ */
+