diff options
author | Dave Barnish <dave.barnish@arm.com> | 2014-07-07 12:20:40 +0100 |
---|---|---|
committer | Dave Barnish <dave.barnish@arm.com> | 2014-07-08 15:37:20 +0100 |
commit | bbb82b80b47b52763fa8a58b68e2d9689d68cd71 (patch) | |
tree | 5f0a6f927272495bc7490428b6f3351f4e013190 | |
parent | f99604d33f315c0d192616f7c225778f01af7a1d (diff) |
Reviewed and revised bo reference counting.
Change-Id: I9d827678692207101565e235b44b62ffee756dc7
-rw-r--r-- | README | 23 | ||||
-rw-r--r-- | src/armsoc_dri2.c | 106 | ||||
-rw-r--r-- | src/armsoc_driver.c | 11 | ||||
-rw-r--r-- | src/armsoc_driver.h | 7 | ||||
-rw-r--r-- | src/armsoc_dumb.c | 17 | ||||
-rw-r--r-- | src/armsoc_dumb.h | 2 | ||||
-rw-r--r-- | src/armsoc_exa.c | 20 | ||||
-rw-r--r-- | src/drmmode_display.c | 35 |
8 files changed, 141 insertions, 80 deletions
@@ -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, ®ion); 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(®ion, &box, 0); ARMSOCDRI2CopyRegion(pDraw, ®ion, 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. |