From 28abba276e36fd0176f416996d44297ddf13f5cd Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 19 Jul 2012 13:46:12 +1000 Subject: nouveau/dri2: add support for DRI2 offload This adds the nouveau interfaces for DRI2 offload, this allows nouveau to act as an offload slave. Signed-off-by: Dave Airlie --- src/nouveau_dri2.c | 147 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 111 insertions(+), 36 deletions(-) diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 62333b1..71cff26 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -21,34 +21,40 @@ nouveau_dri2_buffer(DRI2BufferPtr buf) return (struct nouveau_dri2_buffer *)buf; } +static PixmapPtr get_drawable_pixmap(DrawablePtr drawable) +{ + if (drawable->type == DRAWABLE_PIXMAP) + return (PixmapPtr)drawable; + else + return (*drawable->pScreen->GetWindowPixmap)((WindowPtr)drawable); +} + DRI2BufferPtr -nouveau_dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment, +nouveau_dri2_create_buffer2(ScreenPtr pScreen, DrawablePtr pDraw, unsigned int attachment, unsigned int format) { - ScreenPtr pScreen = pDraw->pScreen; NVPtr pNv = NVPTR(xf86ScreenToScrn(pScreen)); struct nouveau_dri2_buffer *nvbuf; struct nouveau_pixmap *nvpix; - PixmapPtr ppix; + PixmapPtr ppix = NULL; nvbuf = calloc(1, sizeof(*nvbuf)); if (!nvbuf) return NULL; if (attachment == DRI2BufferFrontLeft) { - if (pDraw->type == DRAWABLE_PIXMAP) { - ppix = (PixmapPtr)pDraw; - } else { - WindowPtr pwin = (WindowPtr)pDraw; - ppix = pScreen->GetWindowPixmap(pwin); + ppix = get_drawable_pixmap(pDraw); + if (pScreen != ppix->drawable.pScreen) + ppix = NULL; + if (pDraw->type == DRAWABLE_WINDOW) { #if DRI2INFOREC_VERSION >= 6 /* Set initial swap limit on drawable. */ DRI2SwapLimit(pDraw, pNv->swap_limit); #endif } - - ppix->refcnt++; + if (ppix) + ppix->refcnt++; } else { int bpp; unsigned int usage_hint = NOUVEAU_CREATE_PIXMAP_TILED; @@ -67,31 +73,43 @@ nouveau_dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment, usage_hint); } - pNv->exa_force_cp = TRUE; - exaMoveInPixmap(ppix); - pNv->exa_force_cp = FALSE; + if (ppix) { + pNv->exa_force_cp = TRUE; + exaMoveInPixmap(ppix); + pNv->exa_force_cp = FALSE; + + nvbuf->base.pitch = ppix->devKind; + nvbuf->base.cpp = ppix->drawable.bitsPerPixel / 8; + } nvbuf->base.attachment = attachment; - nvbuf->base.pitch = ppix->devKind; - nvbuf->base.cpp = ppix->drawable.bitsPerPixel / 8; nvbuf->base.driverPrivate = nvbuf; nvbuf->base.format = format; nvbuf->base.flags = 0; nvbuf->ppix = ppix; - nvpix = nouveau_pixmap(ppix); - if (!nvpix || !nvpix->bo || - nouveau_bo_name_get(nvpix->bo, &nvbuf->base.name)) { - pScreen->DestroyPixmap(nvbuf->ppix); - free(nvbuf); - return NULL; + if (ppix) { + nvpix = nouveau_pixmap(ppix); + if (!nvpix || !nvpix->bo || + nouveau_bo_name_get(nvpix->bo, &nvbuf->base.name)) { + pScreen->DestroyPixmap(nvbuf->ppix); + free(nvbuf); + return NULL; + } } - return &nvbuf->base; } +DRI2BufferPtr +nouveau_dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment, + unsigned int format) +{ + return nouveau_dri2_create_buffer2(pDraw->pScreen, pDraw, + attachment, format); +} + void -nouveau_dri2_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buf) +nouveau_dri2_destroy_buffer2(ScreenPtr pScreen, DrawablePtr pDraw, DRI2BufferPtr buf) { struct nouveau_dri2_buffer *nvbuf; @@ -99,38 +117,82 @@ nouveau_dri2_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buf) if (!nvbuf) return; - pDraw->pScreen->DestroyPixmap(nvbuf->ppix); + if (nvbuf->ppix) + pScreen->DestroyPixmap(nvbuf->ppix); free(nvbuf); } void -nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, +nouveau_dri2_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buf) +{ + nouveau_dri2_destroy_buffer2(pDraw->pScreen, pDraw, buf); +} + +void +nouveau_dri2_copy_region2(ScreenPtr pScreen, DrawablePtr pDraw, RegionPtr pRegion, DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer) { struct nouveau_dri2_buffer *src = nouveau_dri2_buffer(pSrcBuffer); struct nouveau_dri2_buffer *dst = nouveau_dri2_buffer(pDstBuffer); - PixmapPtr pspix = src->ppix, pdpix = dst->ppix; - ScreenPtr pScreen = pDraw->pScreen; RegionPtr pCopyClip; GCPtr pGC; - + DrawablePtr src_draw, dst_draw; + Bool translate = FALSE; + int off_x = 0, off_y = 0; + + src_draw = &src->ppix->drawable; + dst_draw = &dst->ppix->drawable; +#if 0 + ErrorF("attachments src %d, dst %d, drawable %p %p pDraw %p\n", + src->base.attachment, dst->base.attachment, + src_draw, dst_draw, pDraw); +#endif if (src->base.attachment == DRI2BufferFrontLeft) - pspix = (PixmapPtr)pDraw; - if (dst->base.attachment == DRI2BufferFrontLeft) - pdpix = (PixmapPtr)pDraw; + src_draw = pDraw; + if (dst->base.attachment == DRI2BufferFrontLeft) { +#ifdef NOUVEAU_PIXMAP_SHARING + if (pDraw->pScreen != pScreen) { + dst_draw = DRI2UpdatePrime(pDraw, pDstBuffer); + if (!dst_draw) + return; + } + else +#endif + dst_draw = pDraw; + } + + if (dst_draw != pDraw) + translate = TRUE; + + if (translate && pDraw->type == DRAWABLE_WINDOW) { + WindowPtr pWin = (WindowPtr)pDraw; + off_x = pWin->origin.x; + off_y = pWin->origin.y; + } pGC = GetScratchGC(pDraw->depth, pScreen); pCopyClip = REGION_CREATE(pScreen, NULL, 0); REGION_COPY(pScreen, pCopyClip, pRegion); - pGC->funcs->ChangeClip(pGC, CT_REGION, pCopyClip, 0); - ValidateGC(&pdpix->drawable, pGC); - pGC->ops->CopyArea(&pspix->drawable, &pdpix->drawable, pGC, 0, 0, - pDraw->width, pDraw->height, 0, 0); + if (translate) { + REGION_TRANSLATE(pScreen, pCopyClip, off_x, off_y); + } + pGC->funcs->ChangeClip(pGC, CT_REGION, pCopyClip, 0); + ValidateGC(dst_draw, pGC); + pGC->ops->CopyArea(src_draw, dst_draw, pGC, 0, 0, + pDraw->width, pDraw->height, off_x, off_y); FreeScratchGC(pGC); } +void +nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, + DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer) +{ + return nouveau_dri2_copy_region2(pDraw->pScreen, pDraw, pRegion, + pDstBuffer, pSrcBuffer); +} + struct nouveau_dri2_vblank_state { enum { SWAP, @@ -169,7 +231,9 @@ update_front(DrawablePtr draw, DRI2BufferPtr front) return FALSE; } - (*draw->pScreen->DestroyPixmap)(nvbuf->ppix); + if (nvbuf->ppix) + (*draw->pScreen->DestroyPixmap)(nvbuf->ppix); + front->pitch = pixmap->devKind; front->cpp = pixmap->drawable.bitsPerPixel / 8; nvbuf->ppix = pixmap; @@ -689,6 +753,17 @@ nouveau_dri2_init(ScreenPtr pScreen) dri2.SwapLimitValidate = nouveau_dri2_swap_limit_validate; #endif +#if DRI2INFOREC_VERSION >= 7 + dri2.version = 7; + dri2.GetParam = NULL; +#endif + +#if DRI2INFOREC_VERSION >= 9 + dri2.version = 9; + dri2.CreateBuffer2 = nouveau_dri2_create_buffer2; + dri2.DestroyBuffer2 = nouveau_dri2_destroy_buffer2; + dri2.CopyRegion2 = nouveau_dri2_copy_region2; +#endif return DRI2ScreenInit(pScreen, &dri2); } -- cgit v1.2.3