summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEskil Sund <eskil.sund@arm.com>2014-04-08 13:11:06 +0000
committerEskil Sund <eskil.sund@arm.com>2014-05-16 17:59:27 +0100
commit1d13da045ced12a123db184fff677b0de41d80e6 (patch)
tree685c756d5a7acd089ea813f1e855fbe9b971b1d1
parent16d0102d7ba794f850f9087c2abe91b900ca4aae (diff)
Enabling n-buffering support when using page flip events.
DRI2INFOREC_VERSION 6 introduces DRI2SwapLimit which enables us to schedule swaps and retrieve next buffer n-times as given by the swap-limit. This further enables us to do asynchronous swaps which enables asynchronous rendering to n-buffers. The swap limit is given by the xorg.conf option DRI2MaxBuffers. If DRI2MaxBuffers is not specified no swap limit will be set and behavior will default to synchronous swaps. Notably, this commit bumps up the required DRI2INFOREC_VERSION to 5 as required by drmAuth. DRI2INFOREC_VERSION 6, with DRI2SwapLimit, is optional. Change-Id: Ia39dcd91628172f884eac914938d8ddd4b41aa71
-rw-r--r--src/armsoc_dri2.c228
-rw-r--r--src/armsoc_driver.h10
-rw-r--r--src/armsoc_dumb.c8
-rw-r--r--src/armsoc_dumb.h2
-rw-r--r--src/armsoc_exa.c17
-rw-r--r--src/drmmode_display.c21
-rw-r--r--src/drmmode_driver.h6
-rw-r--r--src/drmmode_exynos/drmmode_exynos.c1
-rw-r--r--src/drmmode_pl111/drmmode_pl111.c3
-rw-r--r--src/drmmode_template/drmmode_template.c1
10 files changed, 248 insertions, 49 deletions
diff --git a/src/armsoc_dri2.c b/src/armsoc_dri2.c
index 7d05575..ff4583f 100644
--- a/src/armsoc_dri2.c
+++ b/src/armsoc_dri2.c
@@ -36,7 +36,7 @@
#include "dri2.h"
/* any point to support earlier? */
-#if DRI2INFOREC_VERSION < 4
+#if DRI2INFOREC_VERSION < 5
# error "Requires newer DRI2"
#endif
@@ -240,6 +240,13 @@ ARMSOCDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment,
WARNING_MSG(
"Falling back to blitting a flippable window");
}
+#if DRI2INFOREC_VERSION >= 6
+ else if (FALSE == DRI2SwapLimit(pDraw, pARMSOC->swap_chain_size)) {
+ WARNING_MSG(
+ "Failed to set DRI2SwapLimit(%x,%d)",
+ (unsigned int)pDraw, pARMSOC->swap_chain_size);
+ }
+#endif /* DRI2INFOREC_VERSION >= 6 */
}
/* Register Pixmap as having a buffer that can be accessed externally,
@@ -378,6 +385,30 @@ ARMSOCDRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc)
return TRUE;
}
+#if DRI2INFOREC_VERSION >= 6
+/**
+ * Validates that the swap limit range is within the range of supported
+ * asynchronous buffer flips. This is bounded by the DRI2MaxBuffers option plus
+ * one additional flip in case of early display usage.
+ */
+static Bool
+ARMSOCDRI2SwapLimitValidate(DrawablePtr pDraw, int swap_limit) {
+ ScreenPtr pScreen = pDraw->pScreen;
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+ struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn);
+ int32_t lower_limit, upper_limit;
+
+ lower_limit = 1;
+ upper_limit = pARMSOC->driNumBufs-1;
+
+ if (pARMSOC->drmmode_interface->use_early_display)
+ upper_limit += 1;
+
+ return ((swap_limit >= lower_limit) && (swap_limit <= upper_limit))
+ ? TRUE : FALSE;
+}
+#endif /* DRI2INFOREC_VERSION >= 6 */
+
#define ARMSOC_SWAP_FAKE_FLIP (1 << 0)
#define ARMSOC_SWAP_FAIL (1 << 1)
@@ -395,6 +426,10 @@ struct ARMSOCDRISwapCmd {
int swapCount;
int flags;
void *data;
+ struct armsoc_bo *old_src_bo;
+ struct armsoc_bo *old_dst_bo;
+ struct armsoc_bo *new_scanout;
+ int swap_id;
};
static const char * const swap_names[] = {
@@ -517,6 +552,59 @@ static struct armsoc_bo *boFromBuffer(DRI2BufferPtr buf)
return priv->bo;
}
+static
+void updateResizedBuffer(ScrnInfoPtr pScrn, void *buffer,
+ struct armsoc_bo *old_bo, struct armsoc_bo *resized_bo) {
+ DRI2BufferPtr dri2buf = (DRI2BufferPtr)buffer;
+ struct ARMSOCDRI2BufferRec *buf = ARMSOCBUF(dri2buf);
+ int i;
+
+ for (i = 0; i < buf->numPixmaps; i++) {
+ if (buf->pPixmaps[i] != NULL) {
+ struct ARMSOCPixmapPrivRec *priv = exaGetPixmapDriverPrivate(buf->pPixmaps[i]);
+ if (old_bo == priv->bo) {
+ int ret;
+ ret = armsoc_bo_get_name(resized_bo, &dri2buf->name);
+ assert(!ret);
+ priv->bo = resized_bo;
+ }
+ }
+ }
+}
+
+
+void
+ARMSOCDRI2ResizeSwapChain(ScrnInfoPtr pScrn, struct armsoc_bo *old_bo,
+ struct armsoc_bo *resized_bo) {
+ PixmapPtr rootPixmap;
+ struct ARMSOCPixmapPrivRec *rootPriv;
+ struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn);
+ struct ARMSOCDRISwapCmd *cmd = NULL;
+ int i;
+ int back = pARMSOC->swap_chain_count - 1;
+
+ rootPixmap = pScrn->pScreen->GetScreenPixmap(pScrn->pScreen);
+ rootPriv = exaGetPixmapDriverPrivate(rootPixmap);
+ /* We need to access the front to back (count-1) % size. */
+
+ for (i = 0; i < pARMSOC->swap_chain_size && back >= 0; i++) {
+ int idx = back % pARMSOC->swap_chain_size;
+ cmd = pARMSOC->swap_chain[idx];
+ back--;
+ if (!cmd)
+ continue;
+ updateResizedBuffer(pScrn, cmd->pSrcBuffer, old_bo, resized_bo);
+ updateResizedBuffer(pScrn, cmd->pDstBuffer, old_bo, resized_bo);
+ }
+
+ /* The current front buffer might be several frames ahead of scanout. So we
+ * need to check if the current front buffer owned the previous scanout,
+ * i.e. the one we are deleting. If so we will transfer the ownership. */
+ if (0 == armsoc_bo_unreference(old_bo) && rootPriv->bo == old_bo)
+ rootPriv->bo = resized_bo;
+}
+
+
void
ARMSOCDRI2SwapComplete(struct ARMSOCDRISwapCmd *cmd)
{
@@ -524,36 +612,22 @@ ARMSOCDRI2SwapComplete(struct ARMSOCDRISwapCmd *cmd)
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn);
DrawablePtr pDraw = NULL;
+ int idx;
int status;
- struct armsoc_bo *old_src_bo, *old_dst_bo;
if (--cmd->swapCount > 0)
return;
- /* Save the old source bo for unreference below */
- old_src_bo = boFromBuffer(cmd->pSrcBuffer);
- old_dst_bo = boFromBuffer(cmd->pDstBuffer);
-
+ /* If we got signaled a failure we skip the steps below. Instead
+ * we continue and cleanup remains of current swap. */
if ((cmd->flags & ARMSOC_SWAP_FAIL) == 0) {
DEBUG_MSG("%s complete: %d -> %d", swap_names[cmd->type],
cmd->pSrcBuffer->attachment,
cmd->pDstBuffer->attachment);
-
status = dixLookupDrawable(&pDraw, cmd->draw_id, serverClient,
M_ANY, DixWriteAccess);
if (status == Success) {
- if (cmd->type != DRI2_BLIT_COMPLETE &&
- (cmd->flags & ARMSOC_SWAP_FAKE_FLIP) == 0) {
- assert(cmd->type == DRI2_FLIP_COMPLETE);
- exchangebufs(pDraw, cmd->pSrcBuffer,
- cmd->pDstBuffer);
-
- if (cmd->pSrcBuffer->attachment ==
- DRI2BufferBackLeft)
- nextBuffer(pDraw,
- ARMSOCBUF(cmd->pSrcBuffer));
- }
DRI2SwapComplete(cmd->client, pDraw, 0, 0, 0, cmd->type,
cmd->func, cmd->data);
@@ -561,8 +635,7 @@ ARMSOCDRI2SwapComplete(struct ARMSOCDRISwapCmd *cmd)
if (cmd->type != DRI2_BLIT_COMPLETE &&
(cmd->flags & ARMSOC_SWAP_FAKE_FLIP) == 0) {
assert(cmd->type == DRI2_FLIP_COMPLETE);
- set_scanout_bo(pScrn,
- boFromBuffer(cmd->pDstBuffer));
+ set_scanout_bo(pScrn, cmd->new_scanout);
}
}
}
@@ -571,12 +644,18 @@ ARMSOCDRI2SwapComplete(struct ARMSOCDRISwapCmd *cmd)
*/
ARMSOCDRI2DestroyBuffer(pDraw, cmd->pSrcBuffer);
ARMSOCDRI2DestroyBuffer(pDraw, cmd->pDstBuffer);
- armsoc_bo_unreference(old_src_bo);
- armsoc_bo_unreference(old_dst_bo);
+
+ /* drop extra reference of the actual buffer objects used */
+ armsoc_bo_unreference(cmd->old_src_bo);
+ armsoc_bo_unreference(cmd->old_dst_bo);
+
if (cmd->type == DRI2_FLIP_COMPLETE)
pARMSOC->pending_flips--;
- free(cmd);
+ /* Free the swap operation and progress the swap chain. */
+ idx = cmd->swap_id % pARMSOC->swap_chain_size;
+ free(pARMSOC->swap_chain[idx]);
+ pARMSOC->swap_chain[idx] = NULL;
}
/**
@@ -606,6 +685,7 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
struct armsoc_bo *src_bo, *dst_bo;
int src_fb_id, dst_fb_id;
int new_canflip, ret, do_flip;
+ int idx;
RegionRec region;
PixmapPtr pDstPixmap = draw2pix(dri2draw(pDraw, pDstBuffer));
@@ -644,6 +724,19 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
src_fb_id = armsoc_bo_get_fb(src_bo);
dst_fb_id = armsoc_bo_get_fb(dst_bo);
+ /* Store and reference actual buffer-objects used as they could
+ * be exchanged under-the-hood if doing a page flip. */
+ cmd->old_src_bo = src_bo;
+ cmd->old_dst_bo = dst_bo;
+
+ armsoc_bo_reference(src_bo);
+ armsoc_bo_reference(dst_bo);
+
+ /* Add swap operation to the swap chain */
+ cmd->swap_id = pARMSOC->swap_chain_count++;
+ idx = cmd->swap_id % pARMSOC->swap_chain_size;
+ pARMSOC->swap_chain[idx] = cmd;
+
new_canflip = canflip(pDraw);
if ((src->previous_canflip != new_canflip) ||
(dst->previous_canflip != new_canflip)) {
@@ -664,9 +757,6 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
src->previous_canflip = new_canflip;
dst->previous_canflip = new_canflip;
- armsoc_bo_reference(src_bo);
- armsoc_bo_reference(dst_bo);
-
do_flip = src_fb_id && dst_fb_id && canflip(pDraw);
/* After a resolution change the back buffer (src) will still be
@@ -709,6 +799,8 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
else
cmd->swapCount = 0;
+ cmd->new_scanout = boFromBuffer(pDstBuffer);
+
if (cmd->swapCount == 0)
ARMSOCDRI2SwapComplete(cmd);
@@ -722,6 +814,22 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
else
cmd->swapCount = 0;
+ /* Here we have successfully scheduled a flip. We now
+ * need to exchange buffers between src and dst pixmaps
+ * and obtain the next buffer.
+ */
+ if (ret) {
+ assert(cmd->type == DRI2_FLIP_COMPLETE);
+ exchangebufs(pDraw, pSrcBuffer, pDstBuffer);
+
+ if (pSrcBuffer->attachment == DRI2BufferBackLeft)
+ nextBuffer(pDraw, ARMSOCBUF(pSrcBuffer));
+ }
+
+ /* We need to store the new scanout now as the
+ * destination buffer might be switched before the cb. */
+ cmd->new_scanout = boFromBuffer(pDstBuffer);
+
if (cmd->swapCount == 0)
ARMSOCDRI2SwapComplete(cmd);
}
@@ -737,6 +845,7 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
RegionInit(&region, &box, 0);
ARMSOCDRI2CopyRegion(pDraw, &region, pDstBuffer, pSrcBuffer);
cmd->type = DRI2_BLIT_COMPLETE;
+ cmd->new_scanout = boFromBuffer(pDstBuffer);
ARMSOCDRI2SwapComplete(cmd);
}
@@ -769,17 +878,24 @@ ARMSOCDRI2ScreenInit(ScreenPtr pScreen)
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn);
DRI2InfoRec info = {
- .version = 5,
- .fd = pARMSOC->drmFD,
- .driverName = "armsoc",
- .deviceName = pARMSOC->deviceName,
- .CreateBuffer = ARMSOCDRI2CreateBuffer,
- .DestroyBuffer = ARMSOCDRI2DestroyBuffer,
- .CopyRegion = ARMSOCDRI2CopyRegion,
- .ScheduleSwap = ARMSOCDRI2ScheduleSwap,
- .ScheduleWaitMSC = ARMSOCDRI2ScheduleWaitMSC,
- .GetMSC = ARMSOCDRI2GetMSC,
- .AuthMagic = drmAuthMagic,
+#if DRI2INFOREC_VERSION >= 6
+ .version = 6,
+#else
+ .version = 5,
+#endif
+ .fd = pARMSOC->drmFD,
+ .driverName = "armsoc",
+ .deviceName = pARMSOC->deviceName,
+ .CreateBuffer = ARMSOCDRI2CreateBuffer,
+ .DestroyBuffer = ARMSOCDRI2DestroyBuffer,
+ .CopyRegion = ARMSOCDRI2CopyRegion,
+ .ScheduleSwap = ARMSOCDRI2ScheduleSwap,
+ .ScheduleWaitMSC = ARMSOCDRI2ScheduleWaitMSC,
+ .GetMSC = ARMSOCDRI2GetMSC,
+ .AuthMagic = drmAuthMagic,
+#if DRI2INFOREC_VERSION >= 6
+ .SwapLimitValidate = ARMSOCDRI2SwapLimitValidate,
+#endif
};
int minor = 1, major = 0;
@@ -791,6 +907,37 @@ ARMSOCDRI2ScreenInit(ScreenPtr pScreen)
return FALSE;
}
+ /* There is a one-to-one mapping with the DRI2SwapLimit
+ * feature and the swap chain size. If DRI2SwapLimit is
+ * not supported swap-chain will be of size 1.
+ */
+ pARMSOC->swap_chain_size = 1;
+ pARMSOC->swap_chain_count = 0;
+
+ if (FALSE == pARMSOC->NoFlip &&
+ pARMSOC->drmmode_interface->use_page_flip_events) {
+#if DRI2INFOREC_VERSION < 6
+ if (pARMSOC->drmmode_interface->use_early_display ||
+ pARMSOC->driNumBufs > 2)
+ ERROR_MSG("DRI2SwapLimit not supported, but buffers requested are > 2");
+ else
+ WARNING_MSG("DRI2SwapLimit not supported.");
+#else
+ /* Swap chain size or the swap limit must be set to one
+ * less than the number of buffers available unless we
+ * have early display enabled which uses one extra flip.
+ */
+ if (pARMSOC->drmmode_interface->use_early_display)
+ pARMSOC->swap_chain_size = pARMSOC->driNumBufs;
+ else
+ pARMSOC->swap_chain_size = pARMSOC->driNumBufs-1;
+#endif
+ }
+ pARMSOC->swap_chain = calloc(pARMSOC->swap_chain_size,
+ sizeof *pARMSOC->swap_chain);
+
+ INFO_MSG("Setting swap chain size: %d ", pARMSOC->swap_chain_size);
+
return DRI2ScreenInit(pScreen, &info);
}
@@ -807,4 +954,11 @@ ARMSOCDRI2CloseScreen(ScreenPtr pScreen)
drmmode_wait_for_event(pScrn);
}
DRI2CloseScreen(pScreen);
+
+ if (pARMSOC->swap_chain) {
+ int idx = pARMSOC->swap_chain_count % pARMSOC->swap_chain_size;
+ assert(!pARMSOC->swap_chain[idx]);
+ free(pARMSOC->swap_chain);
+ pARMSOC->swap_chain = NULL;
+ }
}
diff --git a/src/armsoc_driver.h b/src/armsoc_driver.h
index 060ac45..e4198ba 100644
--- a/src/armsoc_driver.h
+++ b/src/armsoc_driver.h
@@ -151,6 +151,15 @@ struct ARMSOCRec {
/* Identify which CRTC to use. -1 uses all CRTCs */
int crtcNum;
+ /* The Swap Chain stores the pending swap operations */
+ struct ARMSOCDRISwapCmd **swap_chain;
+
+ /* This is the swap chain's count used to track last swap cmd. */
+ int swap_chain_count;
+
+ /* Defines swap chain size. */
+ int swap_chain_size;
+
};
/*
@@ -209,6 +218,7 @@ struct ARMSOCDRISwapCmd;
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);
/**
* DRI2 util functions..
diff --git a/src/armsoc_dumb.c b/src/armsoc_dumb.c
index eee8904..74f512a 100644
--- a/src/armsoc_dumb.c
+++ b/src/armsoc_dumb.c
@@ -201,14 +201,18 @@ static void armsoc_bo_del(struct armsoc_bo *bo)
free(bo);
}
-void armsoc_bo_unreference(struct armsoc_bo *bo)
+int armsoc_bo_unreference(struct armsoc_bo *bo)
{
+ int refcnt;
if (!bo)
- return;
+ return 0;
assert(bo->refcnt > 0);
+ refcnt = bo->refcnt;
if (--bo->refcnt == 0)
armsoc_bo_del(bo);
+
+ return --refcnt;
}
void armsoc_bo_reference(struct armsoc_bo *bo)
diff --git a/src/armsoc_dumb.h b/src/armsoc_dumb.h
index a299ccf..c808f98 100644
--- a/src/armsoc_dumb.h
+++ b/src/armsoc_dumb.h
@@ -81,7 +81,7 @@ uint32_t armsoc_bo_bpp(struct armsoc_bo *bo);
uint32_t armsoc_bo_pitch(struct armsoc_bo *bo);
void armsoc_bo_reference(struct armsoc_bo *bo);
-void armsoc_bo_unreference(struct armsoc_bo *bo);
+int armsoc_bo_unreference(struct armsoc_bo *bo);
/* When dmabuf is set on a bo, armsoc_bo_cpu_prep()
* waits for KDS shared access
diff --git a/src/armsoc_exa.c b/src/armsoc_exa.c
index 79c8970..f99f772 100644
--- a/src/armsoc_exa.c
+++ b/src/armsoc_exa.c
@@ -136,9 +136,9 @@ ARMSOCDestroyPixmap(ScreenPtr pScreen, void *driverPriv)
struct ARMSOCPixmapPrivRec *priv = driverPriv;
assert(!priv->ext_access_cnt);
-
/* If ModifyPixmapHeader failed, it's possible we don't have a bo
* backing this pixmap. */
+
if (priv->bo) {
assert(!armsoc_bo_has_dmabuf(priv->bo));
armsoc_bo_unreference(priv->bo);
@@ -179,8 +179,18 @@ ARMSOCModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
return FALSE;
}
- if (pPixData == armsoc_bo_map(pARMSOC->scanout))
+ if (pPixData == armsoc_bo_map(pARMSOC->scanout)) {
+ struct armsoc_bo *old_bo = priv->bo;
priv->bo = pARMSOC->scanout;
+ armsoc_bo_reference(priv->bo);
+
+ if (old_bo) {
+ /* We are detaching the old_bo so clear it now. */
+ if (armsoc_bo_has_dmabuf(old_bo))
+ armsoc_bo_clear_dmabuf(old_bo);
+ armsoc_bo_unreference(old_bo);
+ }
+ }
if (priv->usage_hint & ARMSOC_CREATE_PIXMAP_SCANOUT)
buf_type = ARMSOC_BO_SCANOUT;
@@ -211,7 +221,8 @@ ARMSOCModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
armsoc_bo_height(priv->bo) != pPixmap->drawable.height ||
armsoc_bo_bpp(priv->bo) != pPixmap->drawable.bitsPerPixel) {
/* re-allocate buffer! */
- armsoc_bo_unreference(priv->bo);
+ if (priv->bo)
+ armsoc_bo_unreference(priv->bo);
priv->bo = armsoc_bo_new_with_dim(pARMSOC->dev,
pPixmap->drawable.width,
pPixmap->drawable.height,
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 5ad329f..69f0936 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1418,11 +1418,16 @@ drmmode_clones_init(ScrnInfoPtr pScrn, struct drmmode_rec *drmmode)
void set_scanout_bo(ScrnInfoPtr pScrn, struct armsoc_bo *bo)
{
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn);
+ struct armsoc_bo *old_scanout;
+ old_scanout = pARMSOC->scanout;
/* It had better have a framebuffer if we're scanning it out */
assert(armsoc_bo_get_fb(bo));
+ armsoc_bo_reference(bo);
pARMSOC->scanout = bo;
+ if (old_scanout)
+ armsoc_bo_unreference(old_scanout);
}
static Bool resize_scanout_bo(ScrnInfoPtr pScrn, int width, int height)
@@ -1486,6 +1491,7 @@ static Bool resize_scanout_bo(ScrnInfoPtr pScrn, int width, int height)
pitch = armsoc_bo_pitch(pARMSOC->scanout);
} else {
+ struct armsoc_bo *old_scanout = pARMSOC->scanout;
DEBUG_MSG("allocated new scanout buffer okay");
pitch = armsoc_bo_pitch(new_scanout);
/* clear new BO and add FB */
@@ -1502,10 +1508,10 @@ static Bool resize_scanout_bo(ScrnInfoPtr pScrn, int width, int height)
}
/* Handle dma_buf fd that may be attached to old bo */
- if (armsoc_bo_has_dmabuf(pARMSOC->scanout)) {
+ if (armsoc_bo_has_dmabuf(old_scanout)) {
int res;
- armsoc_bo_clear_dmabuf(pARMSOC->scanout);
+ armsoc_bo_clear_dmabuf(old_scanout);
res = armsoc_bo_set_dmabuf(new_scanout);
if (res) {
ERROR_MSG(
@@ -1515,10 +1521,11 @@ static Bool resize_scanout_bo(ScrnInfoPtr pScrn, int width, int height)
return FALSE;
}
}
- /* delete old scanout buffer */
- armsoc_bo_unreference(pARMSOC->scanout);
/* use new scanout buffer */
set_scanout_bo(pScrn, new_scanout);
+
+ /* Resize swap chain will delete old_scanout */
+ ARMSOCDRI2ResizeSwapChain(pScrn, old_scanout, new_scanout);
}
pScrn->displayWidth = pitch / ((pScrn->bitsPerPixel + 7) / 8);
} else
@@ -1556,7 +1563,7 @@ drmmode_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height)
TRACE_ENTER();
if (!resize_scanout_bo(pScrn, width, height))
- return FALSE;
+ goto fail;
/* Framebuffer needs to be reset on all CRTCs, not just
* those that have repositioned */
@@ -1573,6 +1580,10 @@ drmmode_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height)
TRACE_EXIT();
return TRUE;
+
+fail:
+ TRACE_EXIT();
+ return FALSE;
}
static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
diff --git a/src/drmmode_driver.h b/src/drmmode_driver.h
index a46042c..aa31d2b 100644
--- a/src/drmmode_driver.h
+++ b/src/drmmode_driver.h
@@ -43,6 +43,12 @@ struct drmmode_interface {
*/
int use_page_flip_events;
+ /* Boolean value indicating whether to support early display
+ * feature. This allows the next back buffer to be obtained while
+ * the previous is being flipped.
+ */
+ int use_early_display;
+
/* The cursor width */
int cursor_width;
diff --git a/src/drmmode_exynos/drmmode_exynos.c b/src/drmmode_exynos/drmmode_exynos.c
index 91723df..5985cfd 100644
--- a/src/drmmode_exynos/drmmode_exynos.c
+++ b/src/drmmode_exynos/drmmode_exynos.c
@@ -146,6 +146,7 @@ static int create_custom_gem(int fd, struct armsoc_create_gem *create_gem)
struct drmmode_interface exynos_interface = {
1 /* use_page_flip_events */,
+ 1 /* use_early_display */,
CURSORW /* cursor width */,
CURSORH /* cursor_height */,
CURSORPAD /* cursor padding */,
diff --git a/src/drmmode_pl111/drmmode_pl111.c b/src/drmmode_pl111/drmmode_pl111.c
index 2f7f064..7b52168 100644
--- a/src/drmmode_pl111/drmmode_pl111.c
+++ b/src/drmmode_pl111/drmmode_pl111.c
@@ -106,7 +106,8 @@ static int create_custom_gem(int fd, struct armsoc_create_gem *create_gem)
}
struct drmmode_interface pl111_interface = {
- 0 /* use_page_flip_events */,
+ 1 /* use_page_flip_events */,
+ 1 /* use_early_display */,
CURSORW /* cursor width */,
CURSORH /* cursor_height */,
CURSORPAD /* cursor padding */,
diff --git a/src/drmmode_template/drmmode_template.c b/src/drmmode_template/drmmode_template.c
index ccac344..3330a58 100644
--- a/src/drmmode_template/drmmode_template.c
+++ b/src/drmmode_template/drmmode_template.c
@@ -54,6 +54,7 @@ static int create_custom_gem(int fd, struct armsoc_create_gem *create_gem)
struct drmmode_interface template_interface = {
1 /* use_page_flip_events */,
+ 1 /* use_early_display */,
CURSORW /* cursor width */,
CURSORH /* cursor_height */,
CURSORPAD /* cursor padding */,