/** * 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; }