summaryrefslogtreecommitdiff
authorDave Airlie <airlied@redhat.com>2012-07-19 03:46:12 (GMT)
committer Dave Airlie <airlied@redhat.com>2012-09-03 03:12:55 (GMT)
commit28abba276e36fd0176f416996d44297ddf13f5cd (patch) (side-by-side diff)
tree785817b8ee98b4847493e9da2d0359859b5bb600
parentb0be0ac86bae871c9f1724c40298d50d7f2b08e4 (diff)
downloadxf86-video-nouveau-28abba276e36fd0176f416996d44297ddf13f5cd.zip
xf86-video-nouveau-28abba276e36fd0176f416996d44297ddf13f5cd.tar.gz
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 <airlied@redhat.com>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--src/nouveau_dri2.c147
1 files 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);
}