summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Barnish <dave.barnish@arm.com>2014-07-07 12:20:40 +0100
committerDave Barnish <dave.barnish@arm.com>2014-07-08 15:37:20 +0100
commitbbb82b80b47b52763fa8a58b68e2d9689d68cd71 (patch)
tree5f0a6f927272495bc7490428b6f3351f4e013190
parentf99604d33f315c0d192616f7c225778f01af7a1d (diff)
Reviewed and revised bo reference counting.
Change-Id: I9d827678692207101565e235b44b62ffee756dc7
-rw-r--r--README23
-rw-r--r--src/armsoc_dri2.c106
-rw-r--r--src/armsoc_driver.c11
-rw-r--r--src/armsoc_driver.h7
-rw-r--r--src/armsoc_dumb.c17
-rw-r--r--src/armsoc_dumb.h2
-rw-r--r--src/armsoc_exa.c20
-rw-r--r--src/drmmode_display.c35
8 files changed, 141 insertions, 80 deletions
diff --git a/README b/README
index e892d8f..4329914 100644
--- a/README
+++ b/README
@@ -25,3 +25,26 @@ You can also copy src/drmmode_template into src/drmmode_<yourdrivername> and bui
$ ./configure --with-drmmode=<yourdrivername>
+Summary of bo reference counting
+--------------------------------
+The Screen takes a ref on the scanout bo in InitScreen and drops it in ScreenClose. When the scanout bo changes
+(due to a flip or a modeset) the ref is moved from the old bo to the new one by set_scanout_bo.
+
+Pixmaps take a ref on their bo(s) when created in ARMSOCCreatePixmap2 and drop it in ARMSOCDestroyPixmap.
+If ARMSOCModifyPixmapHeader points a pixmap at anything other than the scanout bo then the ref to
+the existing bo (if any) is dropped.
+If ARMSOCModifyPixmapHeader points a pixmap at the scanout bo the ref is moved from the old bo to the new
+If ARMSOCModifyPixmapHeader changes the size of the pixmap's bo the ref is dropped, a new bo created and a
+ref taken on that.
+
+resize_scanout_bo creates and takes a ref on the new bo and drops its ref when the new bo becomes the scanout bo and
+the Screen has taken a ref.
+
+The swap chain takes a ref on the src and dst bos when a swap is scheduled in ARMSOCDRI2ScheduleSwap and drops them
+in ARMSOCDRI2SwapComplete after the src becomes pARMSOC->scanout and the screen takes a ref.
+
+The cursor takes a ref on its bo in drmmode_cursor_init and drops it in drmmode_cursor_fini
+
+
+
+
diff --git a/src/armsoc_dri2.c b/src/armsoc_dri2.c
index a4dfe7d..c0870b1 100644
--- a/src/armsoc_dri2.c
+++ b/src/armsoc_dri2.c
@@ -286,7 +286,7 @@ ARMSOCDRI2DestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer)
if (--buf->refcnt > 0)
return;
- DEBUG_MSG("pDraw=%p, buffer=%p", pDraw, buffer);
+ DEBUG_MSG("pDraw=%p, DRIbuffer=%p", pDraw, buffer);
if (buffer->attachment == DRI2BufferBackLeft) {
assert(pARMSOC->driNumBufs > 1);
@@ -307,6 +307,7 @@ static void
ARMSOCDRI2ReferenceBuffer(DRI2BufferPtr buffer)
{
struct ARMSOCDRI2BufferRec *buf = ARMSOCBUF(buffer);
+
buf->refcnt++;
}
@@ -387,9 +388,9 @@ ARMSOCDRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc)
#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.
+ * Called by DRI2 to validate that any new swap limit being set by
+ * DRI2 is in range. In our case the range is 1 to the DRI2MaxBuffers
+ * option, plus one in the case of early display usage.
*/
static Bool
ARMSOCDRI2SwapLimitValidate(DrawablePtr pDraw, int swap_limit) {
@@ -423,12 +424,12 @@ struct ARMSOCDRISwapCmd {
DRI2BufferPtr pDstBuffer;
DRI2BufferPtr pSrcBuffer;
DRI2SwapEventPtr func;
- int swapCount;
+ int swapCount; /* number of crtcs with flips in flight for this swap */
int flags;
void *data;
- struct armsoc_bo *old_src_bo;
- struct armsoc_bo *old_dst_bo;
- struct armsoc_bo *new_scanout;
+ struct armsoc_bo *old_src_bo; /* Swap chain holds ref on src bo */
+ struct armsoc_bo *old_dst_bo; /* Swap chain holds ref on dst bo */
+ struct armsoc_bo *new_scanout; /* scanout to be used after swap */
unsigned int swap_id;
};
@@ -562,33 +563,40 @@ void updateResizedBuffer(ScrnInfoPtr pScrn, void *buffer,
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);
+
+ /* Update the buffer name if this pixmap is current */
+ if (i == buf->currentPixmap) {
+ ret = armsoc_bo_get_name(resized_bo, &dri2buf->name);
+ assert(!ret);
+ }
+
+ /* pixmap takes ref on resized bo */
+ armsoc_bo_reference(resized_bo);
+ /* replace the old_bo with the resized_bo */
priv->bo = resized_bo;
+ /* pixmap drops ref on old bo */
+ armsoc_bo_unreference(old_bo);
}
}
}
}
-
void
ARMSOCDRI2ResizeSwapChain(ScrnInfoPtr pScrn, struct armsoc_bo *old_bo,
- struct armsoc_bo *resized_bo) {
- PixmapPtr rootPixmap;
- struct ARMSOCPixmapPrivRec *rootPriv;
+ struct armsoc_bo *resized_bo)
+{
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. */
+ int back = pARMSOC->swap_chain_count - 1; /* The last swap scheduled */
+ /* Update the bos for each scheduled swap in the swap chain */
for (i = 0; i < pARMSOC->swap_chain_size && back >= 0; i++) {
unsigned int idx = back % pARMSOC->swap_chain_size;
+
cmd = pARMSOC->swap_chain[idx];
back--;
if (!cmd)
@@ -596,12 +604,6 @@ ARMSOCDRI2ResizeSwapChain(ScrnInfoPtr pScrn, struct armsoc_bo *old_bo,
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;
}
@@ -615,11 +617,12 @@ ARMSOCDRI2SwapComplete(struct ARMSOCDRISwapCmd *cmd)
unsigned int idx;
int status;
- if (--cmd->swapCount > 0)
+ if (--cmd->swapCount > 0) /* wait for all crtcs to flip */
return;
if ((cmd->flags & ARMSOC_SWAP_FAIL) == 0) {
- DEBUG_MSG("%s complete: %d -> %d", swap_names[cmd->type],
+ DEBUG_MSG("swap %d %s complete: %d -> %d",
+ cmd->swap_id, swap_names[cmd->type],
cmd->pSrcBuffer->attachment,
cmd->pDstBuffer->attachment);
status = dixLookupDrawable(&pDraw, cmd->draw_id, serverClient,
@@ -635,7 +638,11 @@ ARMSOCDRI2SwapComplete(struct ARMSOCDRISwapCmd *cmd)
assert(cmd->type == DRI2_FLIP_COMPLETE);
set_scanout_bo(pScrn, cmd->new_scanout);
}
+ } else {
+ ERROR_MSG("dixLookupDrawable fail on swap complete");
}
+ } else {
+ ERROR_MSG("swap %d ARMSOC_SWAP_FAIL on swap complete", cmd->swap_id);
}
/* drop extra refcnt we obtained prior to swap:
@@ -643,14 +650,15 @@ ARMSOCDRI2SwapComplete(struct ARMSOCDRISwapCmd *cmd)
ARMSOCDRI2DestroyBuffer(pDraw, cmd->pSrcBuffer);
ARMSOCDRI2DestroyBuffer(pDraw, cmd->pDstBuffer);
- /* drop extra reference of the actual buffer objects used */
+ /* swap chain drops ref on original src bo */
armsoc_bo_unreference(cmd->old_src_bo);
+ /* swap chain drops ref on original dst bo */
armsoc_bo_unreference(cmd->old_dst_bo);
if (cmd->type == DRI2_FLIP_COMPLETE)
pARMSOC->pending_flips--;
- /* Free the swap operation and progress the swap chain. */
+ /* Free the swap cmd and remove it from the swap chain. */
idx = cmd->swap_id % pARMSOC->swap_chain_size;
assert(pARMSOC->swap_chain[idx] == cmd);
free(cmd);
@@ -709,10 +717,8 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
DamageRegionAppend(&pDstPixmap->drawable, &region);
DamageRegionProcessPending(&pDstPixmap->drawable);
- DEBUG_MSG("%d -> %d", pSrcBuffer->attachment, pDstBuffer->attachment);
-
- /* obtain extra ref on buffers to avoid them going away while we await
- * the page flip event:
+ /* obtain extra ref on DRI buffers to avoid them going
+ * away while we await the page flip event.
*/
ARMSOCDRI2ReferenceBuffer(pSrcBuffer);
ARMSOCDRI2ReferenceBuffer(pDstBuffer);
@@ -723,13 +729,16 @@ 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. */
+ /* Store and reference actual buffer-objects used in case
+ * the pixmaps disappear.
+ */
cmd->old_src_bo = src_bo;
cmd->old_dst_bo = dst_bo;
- armsoc_bo_reference(src_bo);
- armsoc_bo_reference(dst_bo);
+ /* Swap chain takes a ref on original src bo */
+ armsoc_bo_reference(cmd->old_src_bo);
+ /* Swap chain takes a ref on original dst bo */
+ armsoc_bo_reference(cmd->old_dst_bo);
/* Add swap operation to the swap chain */
cmd->swap_id = pARMSOC->swap_chain_count++;
@@ -737,6 +746,9 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
assert(NULL == pARMSOC->swap_chain[idx]);
pARMSOC->swap_chain[idx] = cmd;
+ DEBUG_MSG("SWAP %d SCHEDULED : %d -> %d ", cmd->swap_id,
+ pSrcBuffer->attachment, pDstBuffer->attachment);
+
new_canflip = canflip(pDraw);
if ((src->previous_canflip != new_canflip) ||
(dst->previous_canflip != new_canflip)) {
@@ -775,7 +787,7 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
(armsoc_bo_height(src_bo) == armsoc_bo_height(dst_bo));
if (do_flip) {
- DEBUG_MSG("can flip: %d -> %d", src_fb_id, dst_fb_id);
+ DEBUG_MSG("FLIPPING: FB%d -> FB%d", src_fb_id, dst_fb_id);
cmd->type = DRI2_FLIP_COMPLETE;
/* TODO: MIDEGL-1461: Handle rollback if multiple CRTC flip is
* only partially successful
@@ -800,7 +812,6 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
cmd->swapCount = 0;
cmd->new_scanout = boFromBuffer(pDstBuffer);
-
if (cmd->swapCount == 0)
ARMSOCDRI2SwapComplete(cmd);
@@ -814,9 +825,9 @@ 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.
+ /* Flip successfully scheduled.
+ * Now exchange bos between src and dst pixmaps
+ * and select the next bo for the back buffer.
*/
if (ret) {
assert(cmd->type == DRI2_FLIP_COMPLETE);
@@ -826,10 +837,11 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
nextBuffer(pDraw, ARMSOCBUF(pSrcBuffer));
}
- /* We need to store the new scanout now as the
- * destination buffer might be switched before the cb. */
+ /* Store the new scanout bo now as the destination
+ * buffer bo might be exchanged if another swap is
+ * scheduled before this swap completes
+ */
cmd->new_scanout = boFromBuffer(pDstBuffer);
-
if (cmd->swapCount == 0)
ARMSOCDRI2SwapComplete(cmd);
}
@@ -842,6 +854,8 @@ ARMSOCDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
.y2 = pDraw->height,
};
RegionRec region;
+
+ DEBUG_MSG("BLITTING");
RegionInit(&region, &box, 0);
ARMSOCDRI2CopyRegion(pDraw, &region, pDstBuffer, pSrcBuffer);
cmd->type = DRI2_BLIT_COMPLETE;
@@ -934,7 +948,7 @@ ARMSOCDRI2ScreenInit(ScreenPtr pScreen)
#endif
}
pARMSOC->swap_chain = calloc(pARMSOC->swap_chain_size,
- sizeof *pARMSOC->swap_chain);
+ sizeof(*pARMSOC->swap_chain));
INFO_MSG("Setting swap chain size: %d ", pARMSOC->swap_chain_size);
diff --git a/src/armsoc_driver.c b/src/armsoc_driver.c
index ddd650b..6e21182 100644
--- a/src/armsoc_driver.c
+++ b/src/armsoc_driver.c
@@ -663,7 +663,7 @@ ARMSOCProbe(DriverPtr drv, int flags)
* driverPrivate field.
*/
pScrn->driverPrivate =
- calloc(1, sizeof *pARMSOC);
+ calloc(1, sizeof(*pARMSOC));
if (!pScrn->driverPrivate)
return FALSE;
@@ -973,6 +973,7 @@ ARMSOCScreenInit(SCREEN_INIT_ARGS_DECL)
pScrn->virtualX, pScrn->virtualY,
depth, pScrn->bitsPerPixel);
assert(!pARMSOC->scanout);
+ /* Screen creates and takes a ref on the scanout bo */
pARMSOC->scanout = armsoc_bo_new_with_dim(pARMSOC->dev, pScrn->virtualX,
pScrn->virtualY, depth, pScrn->bitsPerPixel,
ARMSOC_BO_SCANOUT);
@@ -1163,7 +1164,7 @@ fail3:
miClearVisualTypes();
fail2:
- /* release the scanout buffer */
+ /* Screen drops its ref on scanout bo on failure exit */
armsoc_bo_unreference(pARMSOC->scanout);
pARMSOC->scanout = NULL;
pScrn->displayWidth = 0;
@@ -1228,7 +1229,9 @@ ARMSOCCloseScreen(CLOSE_SCREEN_ARGS_DECL)
if (pARMSOC->pARMSOCEXA->CloseScreen)
pARMSOC->pARMSOCEXA->CloseScreen(CLOSE_SCREEN_ARGS);
- /* scanout buffer is released when root pixmap is destroyed */
+ assert(pARMSOC->scanout);
+ /* Screen drops its ref on the scanout buffer */
+ armsoc_bo_unreference(pARMSOC->scanout);
pARMSOC->scanout = NULL;
pScrn->displayWidth = 0;
@@ -1243,8 +1246,6 @@ ARMSOCCloseScreen(CLOSE_SCREEN_ARGS_DECL)
return ret;
}
-
-
/**
* Adjust the screen pixmap for the current location of the front buffer.
* This is done at EnterVT when buffers are bound as long as the resources
diff --git a/src/armsoc_driver.h b/src/armsoc_driver.h
index a22fe5d..4621dcc 100644
--- a/src/armsoc_driver.h
+++ b/src/armsoc_driver.h
@@ -154,12 +154,13 @@ struct ARMSOCRec {
/* 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. */
+ /* Count of swaps scheduled since startup.
+ * Used as swap_id of the next swap cmd */
unsigned int swap_chain_count;
- /* Defines swap chain size. */
+ /* Size of the swap chain. Set to 1 if DRI2SwapLimit unsupported,
+ * driNumBufs if early display enabled, otherwise driNumBufs-1 */
unsigned int swap_chain_size;
-
};
/*
diff --git a/src/armsoc_dumb.c b/src/armsoc_dumb.c
index 74f512a..8f29b7a 100644
--- a/src/armsoc_dumb.c
+++ b/src/armsoc_dumb.c
@@ -70,7 +70,7 @@ struct armsoc_device *armsoc_device_new(int fd,
int (*create_custom_gem)(int fd,
struct armsoc_create_gem *create_gem))
{
- struct armsoc_device *new_dev = calloc(1, sizeof *new_dev);
+ struct armsoc_device *new_dev = calloc(1, sizeof(*new_dev));
if (!new_dev)
return NULL;
@@ -201,18 +201,14 @@ static void armsoc_bo_del(struct armsoc_bo *bo)
free(bo);
}
-int armsoc_bo_unreference(struct armsoc_bo *bo)
+void armsoc_bo_unreference(struct armsoc_bo *bo)
{
- int refcnt;
if (!bo)
- return 0;
+ return;
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)
@@ -361,9 +357,10 @@ int armsoc_bo_add_fb(struct armsoc_bo *bo)
bo->bpp, bo->pitch, bo->handle, &bo->fb_id);
if (ret < 0 && bo->bpp == 32 && bo->depth == 32 && bo->dev->alpha_supported) {
- /* The DRM driver may not support an alpha channel but it is possible
- * to continue by ignoring the alpha, so if an attempt to create
- * a depth 32, bpp 32 framebuffer fails we retry with depth 24, bpp 32
+ /* The DRM driver may not support an alpha channel but
+ * it is possible to continue by ignoring the alpha, so
+ * if an attempt to create a depth 32, bpp 32 framebuffer
+ * fails we retry with depth 24, bpp 32
*/
xf86DrvMsg(-1, X_WARNING,
"depth 32 FB unsupported : falling back to depth 24\n");
diff --git a/src/armsoc_dumb.h b/src/armsoc_dumb.h
index c808f98..a299ccf 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);
-int armsoc_bo_unreference(struct armsoc_bo *bo);
+void 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 fc897ef..a578a27 100644
--- a/src/armsoc_exa.c
+++ b/src/armsoc_exa.c
@@ -1,4 +1,3 @@
-/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
/*
* Copyright © 2011 Texas Instruments, Inc
@@ -78,7 +77,7 @@ ARMSOCCreatePixmap2(ScreenPtr pScreen, int width, int height,
int depth, int usage_hint, int bitsPerPixel,
int *new_fb_pitch)
{
- struct ARMSOCPixmapPrivRec *priv = calloc(1, sizeof *priv);
+ struct ARMSOCPixmapPrivRec *priv = calloc(1, sizeof(*priv));
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn);
enum armsoc_buf_type buf_type = ARMSOC_BO_NON_SCANOUT;
@@ -90,6 +89,7 @@ ARMSOCCreatePixmap2(ScreenPtr pScreen, int width, int height,
buf_type = ARMSOC_BO_SCANOUT;
if (width > 0 && height > 0 && depth > 0 && bitsPerPixel > 0) {
+ /* Pixmap creates and takes a ref on its bo */
priv->bo = armsoc_bo_new_with_dim(pARMSOC->dev,
width,
height,
@@ -103,6 +103,7 @@ ARMSOCCreatePixmap2(ScreenPtr pScreen, int width, int height,
WARNING_MSG(
"Scanout buffer allocation failed, falling back to non-scanout");
buf_type = ARMSOC_BO_NON_SCANOUT;
+ /* Pixmap creates and takes a ref on its bo */
priv->bo = armsoc_bo_new_with_dim(pARMSOC->dev,
width,
height,
@@ -141,6 +142,7 @@ ARMSOCDestroyPixmap(ScreenPtr pScreen, void *driverPriv)
* backing this pixmap. */
if (priv->bo) {
assert(!armsoc_bo_has_dmabuf(priv->bo));
+ /* pixmap drops ref on its bo */
armsoc_bo_unreference(priv->bo);
}
@@ -172,6 +174,10 @@ ARMSOCModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
/* scratch-pixmap (see GetScratchPixmapHeader()) gets recycled,
* so could have a previous bo!
*/
+
+ /* scratch pixmap should not have a dmabuf */
+ assert(!armsoc_bo_has_dmabuf(priv->bo));
+ /* Pixmap drops ref on its old bo */
armsoc_bo_unreference(priv->bo);
priv->bo = NULL;
@@ -179,15 +185,19 @@ ARMSOCModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
return FALSE;
}
- if (pPixData == armsoc_bo_map(pARMSOC->scanout)) {
+ /* Replacing the pixmap's current bo with the scanout bo */
+ if (pPixData == armsoc_bo_map(pARMSOC->scanout) && priv->bo != pARMSOC->scanout) {
struct armsoc_bo *old_bo = priv->bo;
+
priv->bo = pARMSOC->scanout;
+ /* pixmap takes a ref on its new bo */
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);
+ /* pixmap drops ref on previous bo */
armsoc_bo_unreference(old_bo);
}
}
@@ -220,8 +230,9 @@ ARMSOCModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
if (armsoc_bo_width(priv->bo) != pPixmap->drawable.width ||
armsoc_bo_height(priv->bo) != pPixmap->drawable.height ||
armsoc_bo_bpp(priv->bo) != pPixmap->drawable.bitsPerPixel) {
- /* re-allocate buffer! */
+ /* pixmap drops ref on its old bo */
armsoc_bo_unreference(priv->bo);
+ /* pixmap creates new bo and takes ref on it */
priv->bo = armsoc_bo_new_with_dim(pARMSOC->dev,
pPixmap->drawable.width,
pPixmap->drawable.height,
@@ -235,6 +246,7 @@ ARMSOCModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
WARNING_MSG(
"Scanout buffer allocation failed, falling back to non-scanout");
buf_type = ARMSOC_BO_NON_SCANOUT;
+ /* pixmap creates new bo and takes ref on it */
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 ca7a42e..bfa1905 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1458,10 +1458,10 @@ void set_scanout_bo(ScrnInfoPtr pScrn, struct armsoc_bo *bo)
/* It had better have a framebuffer if we're scanning it out */
assert(armsoc_bo_get_fb(bo));
- armsoc_bo_reference(bo);
+ armsoc_bo_reference(bo); /* Screen takes ref on new scanout bo */
pARMSOC->scanout = bo;
if (old_scanout)
- armsoc_bo_unreference(old_scanout);
+ armsoc_bo_unreference(old_scanout); /* Screen drops ref on old scanout bo */
}
static Bool resize_scanout_bo(ScrnInfoPtr pScrn, int width, int height)
@@ -1475,12 +1475,12 @@ static Bool resize_scanout_bo(ScrnInfoPtr pScrn, int width, int height)
depth = armsoc_bo_depth(pARMSOC->scanout);
bpp = armsoc_bo_bpp(pARMSOC->scanout);
- DEBUG_MSG("Resize: %dx%d %d,%d", width, height, depth, bpp );
+ DEBUG_MSG("Resize: %dx%d %d,%d", width, height, depth, bpp);
/* We don't expect the depth and bpp to change for the screen
* assert this here as a check */
- assert( depth == pScrn->bitsPerPixel );
- assert( bpp == pScrn->bitsPerPixel );
+ assert(depth == pScrn->bitsPerPixel);
+ assert(bpp == pScrn->bitsPerPixel);
pScrn->virtualX = width;
pScrn->virtualY = height;
@@ -1489,7 +1489,7 @@ static Bool resize_scanout_bo(ScrnInfoPtr pScrn, int width, int height)
(height != armsoc_bo_height(pARMSOC->scanout))) {
struct armsoc_bo *new_scanout;
- /* allocate new scanout buffer */
+ /* resize_scanout_bo creates and takes ref on new scanout bo */
new_scanout = armsoc_bo_new_with_dim(pARMSOC->dev,
width, height,
depth, bpp,
@@ -1526,10 +1526,12 @@ 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 */
if (armsoc_bo_clear(new_scanout)) {
+ /* resize_scanout_bo drops ref on new scanout on failure exit */
armsoc_bo_unreference(new_scanout);
return FALSE;
}
@@ -1537,6 +1539,7 @@ static Bool resize_scanout_bo(ScrnInfoPtr pScrn, int width, int height)
if (armsoc_bo_add_fb(new_scanout)) {
ERROR_MSG(
"Failed to add framebuffer to the new scanout buffer");
+ /* resize_scanout_bo drops ref on new scanout on failure exit */
armsoc_bo_unreference(new_scanout);
return FALSE;
}
@@ -1551,14 +1554,14 @@ static Bool resize_scanout_bo(ScrnInfoPtr pScrn, int width, int height)
ERROR_MSG(
"Unable to attach dma_buf fd to new scanout buffer - %d (%s)\n",
res, strerror(res));
- armsoc_bo_unreference(new_scanout);
+ armsoc_bo_unreference(new_scanout); /* resize_scanout_bo drops ref on new scanout on failure exit */
return FALSE;
}
}
/* use new scanout buffer */
set_scanout_bo(pScrn, new_scanout);
+ armsoc_bo_unreference(new_scanout); /* Screen has now taken ref on new_scanout so resize_scanout_bo drops it */
- /* Resize swap chain will delete old_scanout */
ARMSOCDRI2ResizeSwapChain(pScrn, old_scanout, new_scanout);
}
pScrn->displayWidth = pitch / ((pScrn->bitsPerPixel + 7) / 8);
@@ -1568,10 +1571,20 @@ static Bool resize_scanout_bo(ScrnInfoPtr pScrn, int width, int height)
if (pScreen && pScreen->ModifyPixmapHeader) {
PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
+ /* Wrap the screen pixmap around the new scanout bo.
+ * If we are n-buffering and the scanout bo is behind the
+ * screen pixmap by a few flips, the bo which is being resized
+ * may not belong to the screen pixmap. However we need to
+ * resize the screen pixmap in order to continue flipping.
+ * For now we let this happen and the swap chain reference
+ * on the screen pixmap's existing bo will prevent it being
+ * deleted here. Things may look odd until the swap chain
+ * works through. This needs improvement.
+ */
pScreen->ModifyPixmapHeader(rootPixmap,
- pScrn->virtualX, pScrn->virtualY,
- depth, bpp, pitch,
- armsoc_bo_map(pARMSOC->scanout));
+ pScrn->virtualX, pScrn->virtualY,
+ depth, bpp, pitch,
+ armsoc_bo_map(pARMSOC->scanout));
/* Bump the serial number to ensure that all existing DRI2
* buffers are invalidated.