/** * Get current frame count and frame count timestamp, based on drawable's * crtc. */ static int ARMSOCDRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc) { ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); drmVBlank vbl = { .request = { .type = DRM_VBLANK_RELATIVE, .sequence = 0, } }; int ret; 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; } if (ust) *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec; if (msc) *msc = vbl.reply.sequence; return TRUE; }
/** * CloseScreen() is called at the end of each server generation and * cleans up everything initialised in InitNullEXA() */ static Bool CloseScreen(CLOSE_SCREEN_ARGS_DECL) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); exaDriverFini(pScreen); free(((struct ARMSOCNullEXARec *)pARMSOC->pARMSOCEXA)->exa); free(pARMSOC->pARMSOCEXA); pARMSOC->pARMSOCEXA = NULL; return TRUE; }
static Bool canflip(DrawablePtr pDraw) { ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); if (pARMSOC->NoFlip) { /* flipping is disabled by user option */ return FALSE; } else { return (pDraw->type == DRAWABLE_WINDOW) && DRI2CanFlip(pDraw); } }
/** * 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) { 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; }
static Bool destroy_buffer(DrawablePtr pDraw, struct ARMSOCDRI2BufferRec *buf) { 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 FALSE; if (buffer->attachment == DRI2BufferBackLeft) { assert(pARMSOC->driNumBufs > 1); numBuffers = pARMSOC->driNumBufs-1; } else numBuffers = 1; for (i = 0; i < numBuffers && buf->pPixmaps[i] != NULL; i++) { ARMSOCDeregisterExternalAccess(buf->pPixmaps[i]); pScreen->DestroyPixmap(buf->pPixmaps[i]); } return TRUE; }
/* keep this here, instead of static-inline so submodule doesn't * need to know layout of ARMSOCRec. */ _X_EXPORT struct ARMSOCEXARec * ARMSOCEXAPTR(ScrnInfoPtr pScrn) { struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); return pARMSOC->pARMSOCEXA; }
/** * 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 = calloc(1, sizeof(*buf)); struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); struct armsoc_bo *bo; DEBUG_MSG("pDraw=%p, attachment=%d, format=%08x", pDraw, attachment, format); if (!buf) { ERROR_MSG("Couldn't allocate internal buffer structure"); return NULL; } buf->refcnt = 1; buf->previous_canflip = canflip(pDraw); DRIBUF(buf)->attachment = attachment; DRIBUF(buf)->cpp = pDraw->bitsPerPixel / 8; DRIBUF(buf)->format = format + 1; /* suppress DRI2 buffer reuse */ DRIBUF(buf)->flags = 0; /* If it is a pixmap, just migrate to a GEM buffer */ if (pDraw->type == DRAWABLE_PIXMAP) { if (!(bo = MigratePixmapToGEM(pARMSOC, pDraw))) { ErrorF("ARMSOCDRI2CreateBuffer: MigratePixmapToUMP failed\n"); free(buf); return NULL; } DRIBUF(buf)->pitch = armsoc_bo_pitch(bo); DRIBUF(buf)->name = armsoc_bo_name(bo); buf->bo = bo; return DRIBUF(buf); } /* We are not interested in anything other than back buffer requests ... */ if (attachment != DRI2BufferBackLeft || pDraw->type != DRAWABLE_WINDOW) { /* ... and just return some dummy UMP buffer */ bo = pARMSOC->scanout; DRIBUF(buf)->pitch = armsoc_bo_pitch(bo); DRIBUF(buf)->name = armsoc_bo_name(bo); buf->bo = bo; armsoc_bo_reference(bo); return DRIBUF(buf); } bo = armsoc_bo_from_drawable(pDraw); if (bo && armsoc_bo_width(bo) == pDraw->width && armsoc_bo_height(bo) == pDraw->height && armsoc_bo_bpp(bo) == pDraw->bitsPerPixel) { // Reuse existing DRIBUF(buf)->pitch = armsoc_bo_pitch(bo); DRIBUF(buf)->name = armsoc_bo_name(bo); buf->bo = bo; armsoc_bo_reference(bo); return DRIBUF(buf); } bo = armsoc_bo_new_with_dim(pARMSOC->dev, pDraw->width, pDraw->height, pDraw->depth, pDraw->bitsPerPixel, canflip(pDraw) ? ARMSOC_BO_SCANOUT : ARMSOC_BO_NON_SCANOUT); if (!bo) { ErrorF("ARMSOCDRI2CreateBuffer: BO alloc failed\n"); free(buf); return NULL; } armsoc_bo_set_drawable(bo, pDraw); DRIBUF(buf)->name = armsoc_bo_name(bo); DRIBUF(buf)->pitch = armsoc_bo_pitch(bo); buf->bo = bo; if (canflip(pDraw) && 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 * support the format or there was insufficient scanout memory * at buffer creation time). */ int ret = armsoc_bo_add_fb(bo); if (ret) { WARNING_MSG( "Falling back to blitting a flippable window"); } } /* Register Pixmap as having a buffer that can be accessed externally, * so needs synchronised access */ // FIXME ARMSOCRegisterExternalAccess(pPixmap); return DRIBUF(buf); }
static Bool create_buffer(DrawablePtr pDraw, struct ARMSOCDRI2BufferRec *buf) { ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); DRI2BufferPtr buffer = DRIBUF(buf); PixmapPtr pPixmap = NULL; struct armsoc_bo *bo; int ret; if (buffer->attachment == DRI2BufferFrontLeft) { pPixmap = draw2pix(pDraw); pPixmap->refcnt++; } else { pPixmap = createpix(pDraw); } if (!pPixmap) { assert(buffer->attachment != DRI2BufferFrontLeft); ERROR_MSG("Failed to create back buffer for window"); goto fail; } if (buffer->attachment == DRI2BufferBackLeft && pARMSOC->driNumBufs > 2) { buf->pPixmaps = calloc(pARMSOC->driNumBufs-1, sizeof(PixmapPtr)); buf->numPixmaps = pARMSOC->driNumBufs-1; } else { buf->pPixmaps = malloc(sizeof(PixmapPtr)); buf->numPixmaps = 1; } if (!buf->pPixmaps) { ERROR_MSG("Failed to allocate PixmapPtr array for DRI2Buffer"); goto fail; } buf->pPixmaps[0] = pPixmap; assert(buf->currentPixmap == 0); bo = ARMSOCPixmapBo(pPixmap); if (!bo) { ERROR_MSG( "Attempting to DRI2 wrap a pixmap with no DRM buffer object backing"); goto fail; } DRIBUF(buf)->pitch = exaGetPixmapPitch(pPixmap); DRIBUF(buf)->cpp = pPixmap->drawable.bitsPerPixel / 8; DRIBUF(buf)->flags = 0; buf->refcnt = 1; buf->previous_canflip = canflip(pDraw); ret = armsoc_bo_get_name(bo, &DRIBUF(buf)->name); if (ret) { ERROR_MSG("could not get buffer name: %d", ret); goto fail; } 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 * support the format or there was insufficient scanout memory * at buffer creation time). */ int ret = armsoc_bo_add_fb(bo); if (ret) { 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 */ } 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 TRUE; fail: if (pPixmap != NULL) { if (buffer->attachment != DRI2BufferFrontLeft) pScreen->DestroyPixmap(pPixmap); else pPixmap->refcnt--; } return FALSE; }