diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2014-06-19 14:54:20 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2014-06-19 15:57:35 +1000 |
commit | 86024ceef015ffe31a204cc5bc6c326a19363ff1 (patch) | |
tree | b9463ea3dab5f6d98ecab8604526d715bd3371c8 | |
parent | fd0ce8839f307693d86c7602dd926ce79e6b777d (diff) |
glamor: initial support (no dri)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | configure.ac | 9 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/drmmode_display.c | 19 | ||||
-rw-r--r-- | src/nouveau_glamor.c | 244 | ||||
-rw-r--r-- | src/nouveau_glamor.h | 30 | ||||
-rw-r--r-- | src/nouveau_wfb.c | 12 | ||||
-rw-r--r-- | src/nouveau_xv.c | 5 | ||||
-rw-r--r-- | src/nv_driver.c | 29 | ||||
-rw-r--r-- | src/nv_type.h | 1 |
9 files changed, 338 insertions, 13 deletions
diff --git a/configure.ac b/configure.ac index c524660..c34e575 100644 --- a/configure.ac +++ b/configure.ac @@ -127,6 +127,15 @@ AC_SUBST([DRIVER_NAME]) XORG_MANPAGE_SECTIONS XORG_RELEASE_VERSION +AC_MSG_CHECKING([whether to include GLAMOR support]) +if pkg-config --exists "xorg-server >= 1.15.99.901" +then + AC_DEFINE(HAVE_GLAMOR, 1, [Build support for glamor acceleration]) + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + AC_CONFIG_FILES([ Makefile src/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index 248298e..9fe8000 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -35,6 +35,7 @@ nouveau_drv_la_SOURCES = \ nouveau_copy90b5.c \ nouveau_copya0b5.c \ nouveau_exa.c nouveau_xv.c nouveau_dri2.c \ + nouveau_glamor.c \ nouveau_wfb.c \ nv_accel_common.c \ nv_driver.c \ @@ -120,6 +121,7 @@ EXTRA_DIST = hwdefs/nv_3ddefs.xml.h \ shader/Makefile \ nouveau_local.h \ nouveau_copy.h \ + nouveau_glamor.h \ nv_const.h \ nv_dma.h \ nv_include.h \ diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 3d0cfd1..c87cff3 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -42,6 +42,8 @@ #include "libudev.h" #endif +#include "nouveau_glamor.h" + static Bool drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height); typedef struct { int fd; @@ -115,6 +117,15 @@ drmmode_from_scrn(ScrnInfoPtr scrn) return NULL; } +static inline struct nouveau_pixmap * +drmmode_pixmap(PixmapPtr ppix) +{ + NVPtr pNv = NVPTR(xf86ScreenToScrn(ppix->drawable.pScreen)); + if (pNv->AccelMethod == GLAMOR) + return nouveau_glamor_pixmap_get(ppix); + return nouveau_pixmap(ppix); +} + static PixmapPtr drmmode_pixmap_wrap(ScreenPtr pScreen, int width, int height, int depth, int bpp, int pitch, struct nouveau_bo *bo, void *data) @@ -132,7 +143,7 @@ drmmode_pixmap_wrap(ScreenPtr pScreen, int width, int height, int depth, pScreen->ModifyPixmapHeader(ppix, width, height, depth, bpp, pitch, data); if (pNv->AccelMethod > NONE) - nouveau_bo_ref(bo, &nouveau_pixmap(ppix)->bo); + nouveau_bo_ref(bo, &drmmode_pixmap(ppix)->bo); return ppix; } @@ -1221,8 +1232,8 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) } ppix = screen->GetScreenPixmap(screen); - if (pNv->AccelMethod > NONE) - nouveau_bo_ref(pNv->scanout, &nouveau_pixmap(ppix)->bo); + if (pNv->AccelMethod >= NONE) + nouveau_bo_ref(pNv->scanout, &drmmode_pixmap(ppix)->bo); screen->ModifyPixmapHeader(ppix, width, height, -1, -1, pitch, (pNv->AccelMethod > NONE || pNv->ShadowPtr) ? pNv->ShadowPtr : pNv->scanout->map); @@ -1379,7 +1390,7 @@ drmmode_page_flip(DrawablePtr draw, PixmapPtr back, void *priv, ret = drmModeAddFB(mode->fd, scrn->virtualX, scrn->virtualY, scrn->depth, scrn->bitsPerPixel, scrn->displayWidth * scrn->bitsPerPixel / 8, - nouveau_pixmap_bo(back)->handle, &mode->fb_id); + drmmode_pixmap(back)->bo->handle, &mode->fb_id); if (ret) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "add fb failed: %s\n", strerror(errno)); diff --git a/src/nouveau_glamor.c b/src/nouveau_glamor.c new file mode 100644 index 0000000..688fc76 --- /dev/null +++ b/src/nouveau_glamor.c @@ -0,0 +1,244 @@ +/* + * Copyright 2014 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#include "nouveau_glamor.h" +#ifdef HAVE_GLAMOR + +static DevPrivateKeyRec glamor_private; + +static inline void +nouveau_glamor_pixmap_set(PixmapPtr pixmap, struct nouveau_pixmap *priv) +{ + dixSetPrivate(&pixmap->devPrivates, &glamor_private, priv); +} + +struct nouveau_pixmap * +nouveau_glamor_pixmap_get(PixmapPtr pixmap) +{ + return dixGetPrivate(&pixmap->devPrivates, &glamor_private); +} + +static Bool +nouveau_glamor_destroy_pixmap(PixmapPtr pixmap) +{ + struct nouveau_pixmap *priv = nouveau_glamor_pixmap_get(pixmap); + if (pixmap->refcnt == 1) { + glamor_egl_destroy_textured_pixmap(pixmap); + if (priv) + nouveau_bo_ref(NULL, &priv->bo); + } + fbDestroyPixmap(pixmap); + return TRUE; +} + +static PixmapPtr +nouveau_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, + unsigned usage) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + struct nouveau_pixmap *priv; + PixmapPtr pixmap; + int pitch; + + if (usage != CREATE_PIXMAP_USAGE_SHARED) + return glamor_create_pixmap(screen, w, h, depth, usage); + if (depth == 1) + return fbCreatePixmap(screen, w, h, depth, usage); + if (w > 32767 || h > 32767) + return NullPixmap; + + pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); + if (pixmap == NullPixmap || !w || !h) + return pixmap; + + priv = calloc(1, sizeof(*priv)); + if (!priv) + goto fail_priv; + + if (!nouveau_allocate_surface(scrn, w, h, + pixmap->drawable.bitsPerPixel, + usage, &pitch, &priv->bo)) + goto fail_bo; + + nouveau_glamor_pixmap_set(pixmap, priv); + screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL); + + if (!glamor_egl_create_textured_pixmap(pixmap, priv->bo->handle, + pixmap->devKind)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "[GLAMOR] failed to create textured PRIME pixmap."); + return pixmap; + } + + return pixmap; +fail_bo: + free(priv); +fail_priv: + fbDestroyPixmap(pixmap); + return fbCreatePixmap(screen, w, h, depth, usage); +} + +static Bool +nouveau_glamor_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, + void **phandle) +{ + struct nouveau_pixmap *priv = nouveau_glamor_pixmap_get(pixmap); + int ret, handle; + + ret = nouveau_bo_set_prime(priv->bo, &handle); + if (ret) + return FALSE; + + priv->shared = TRUE; + *phandle = (void *)(long)handle; + return TRUE; +} + +static Bool +nouveau_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void *_handle) +{ + struct nouveau_pixmap *priv = nouveau_glamor_pixmap_get(pixmap); + ScreenPtr screen = pixmap->drawable.pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + NVPtr pNv = NVPTR(scrn); + struct nouveau_bo *bo; + int ret, handle = (int)(long)_handle; + + ret = nouveau_bo_prime_handle_ref(pNv->dev, handle, &bo); + if (ret) + return FALSE; + + priv->bo = bo; + priv->shared = TRUE; + close(handle); + + if (!glamor_egl_create_textured_pixmap(pixmap, priv->bo->handle, + pixmap->devKind)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "[GLAMOR] failed to get PRIME drawable\n"); + return FALSE; + } + + return TRUE; +} + +static void +nouveau_glamor_flush(ScrnInfoPtr pScrn) +{ + glamor_block_handler(pScrn->pScreen); +} + +Bool +nouveau_glamor_create_screen_resources(ScreenPtr screen) +{ + struct nouveau_pixmap *priv = calloc(1, sizeof(*priv)); + PixmapPtr ppix = screen->GetScreenPixmap(screen); + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + NVPtr pNv = NVPTR(scrn); + + if (!glamor_glyphs_init(screen)) + goto fail; + + if (!glamor_egl_create_textured_screen_ext(screen, + pNv->scanout->handle, + scrn->displayWidth * + scrn->bitsPerPixel / 8, + NULL)) + goto fail; + + nouveau_glamor_pixmap_set(ppix, priv); + return TRUE; +fail: + free(priv); + return FALSE; +} + +Bool +nouveau_glamor_pre_init(ScrnInfoPtr scrn) +{ + NVPtr pNv = NVPTR(scrn); + pointer glamor_module; + + if (scrn->depth < 24) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "[GLAMOR] requires depth >= 24\n"); + return FALSE; + } + + if ((glamor_module = xf86LoadSubModule(scrn, GLAMOR_EGL_MODULE_NAME))) { + if (!glamor_egl_init(scrn, pNv->dev->fd)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "[GLAMOR] failed to initialise EGL\n"); + return FALSE; + } + } else { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, "[GLAMOR] unavailable\n"); + return FALSE; + } + + xf86DrvMsg(scrn->scrnIndex, X_INFO, "[GLAMOR] EGL initialised\n"); + return TRUE; +} + +Bool +nouveau_glamor_init(ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + NVPtr pNv = NVPTR(scrn); + + if (!glamor_init(screen, GLAMOR_INVERTED_Y_AXIS | + GLAMOR_USE_EGL_SCREEN | + GLAMOR_USE_SCREEN | + GLAMOR_USE_PICTURE_SCREEN | + GLAMOR_NO_DRI3)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "[GLAMOR] failed to initialise\n"); + return FALSE; + } + + if (!glamor_egl_init_textured_pixmap(screen)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "[GLAMOR] failed to initialize screen pixmap\n"); + return FALSE; + } + + if (!dixRegisterPrivateKey(&glamor_private, PRIVATE_PIXMAP, 0)) + return FALSE; + + screen->CreatePixmap = nouveau_glamor_create_pixmap; + screen->DestroyPixmap = nouveau_glamor_destroy_pixmap; + screen->SharePixmapBacking = nouveau_glamor_share_pixmap_backing; + screen->SetSharedPixmapBacking = nouveau_glamor_set_shared_pixmap_backing; + + xf86DrvMsg(scrn->scrnIndex, X_INFO, "[GLAMOR] initialised\n"); + pNv->Flush = nouveau_glamor_flush; + return TRUE; +} + +XF86VideoAdaptorPtr +nouveau_glamor_xv_init(ScreenPtr pScreen, int num_adapt) +{ + return glamor_xv_init(pScreen, num_adapt); +} +#endif diff --git a/src/nouveau_glamor.h b/src/nouveau_glamor.h new file mode 100644 index 0000000..ef01317 --- /dev/null +++ b/src/nouveau_glamor.h @@ -0,0 +1,30 @@ +#ifndef __NOUVEAU_GLAMOR_H__ +#define __NOUVEAU_GLAMOR_H__ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "xf86xv.h" + +#ifdef HAVE_GLAMOR +#include "nv_include.h" +#define GLAMOR_FOR_XORG 1 +#include "glamor.h" + +Bool nouveau_glamor_pre_init(ScrnInfoPtr scrn); +Bool nouveau_glamor_init(ScreenPtr screen); +Bool nouveau_glamor_create_screen_resources(ScreenPtr screen); +XF86VideoAdaptorPtr nouveau_glamor_xv_init(ScreenPtr pScreen, int num_adapt); +struct nouveau_pixmap *nouveau_glamor_pixmap_get(PixmapPtr pixmap); +#else +static inline Bool nouveau_glamor_pre_init(ScrnInfoPtr scrn) { return FALSE; } +static inline Bool nouveau_glamor_init(ScreenPtr screen) { return FALSE; } +static inline Bool +nouveau_glamor_create_screen_resources(ScreenPtr screen) { return FALSE; } +static inline struct nouveau_pixmap * +nouveau_glamor_pixmap_get(PixmapPtr pixmap) { return NULL; } +static inline XF86VideoAdaptorPtr +nouveau_glamor_xv_init(ScreenPtr pScreen, int num_adapt) { return NULL; } +#endif + +#endif diff --git a/src/nouveau_wfb.c b/src/nouveau_wfb.c index d95d162..10f0f27 100644 --- a/src/nouveau_wfb.c +++ b/src/nouveau_wfb.c @@ -26,6 +26,7 @@ */ #include "nv_include.h" +#include "nouveau_glamor.h" struct wfb_pixmap { PixmapPtr ppix; @@ -134,8 +135,15 @@ nouveau_wfb_setup_wrap(ReadMemoryProcPtr *pRead, WriteMemoryProcPtr *pWrite, return; ppix = NVGetDrawablePixmap(pDraw); - if (ppix) - bo = nouveau_pixmap_bo(ppix); + if (ppix) { + NVPtr pNv = NVPTR(xf86ScreenToScrn(pDraw->pScreen)); + struct nouveau_pixmap *priv; + if (pNv->AccelMethod == GLAMOR) + priv = nouveau_glamor_pixmap_get(ppix); + else + priv = nouveau_pixmap(ppix); + bo = priv ? priv->bo : NULL; + } if (!ppix || !bo) { for (i = 0; i < 6; i++) diff --git a/src/nouveau_xv.c b/src/nouveau_xv.c index 31a7950..e40d6ba 100644 --- a/src/nouveau_xv.c +++ b/src/nouveau_xv.c @@ -38,7 +38,7 @@ #include "nv_include.h" #include "nv_dma.h" - +#include "nouveau_glamor.h" #include "vl_hwmc.h" @@ -2088,6 +2088,9 @@ NVInitVideo(ScreenPtr pScreen) } NVSetupTexturedVideo(pScreen, textureAdaptor); + } else + if (pNv->AccelMethod == GLAMOR) { + blitAdaptor = nouveau_glamor_xv_init(pScreen, 16); } num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); diff --git a/src/nv_driver.c b/src/nv_driver.c index b7d8e87..9396958 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -33,6 +33,7 @@ #endif #include "nouveau_copy.h" +#include "nouveau_glamor.h" /* * Forward definitions for the functions that make up the driver. @@ -580,7 +581,6 @@ NVCreateScreenResources(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); NVPtr pNv = NVPTR(pScrn); - PixmapPtr ppix; pScreen->CreateScreenResources = pNv->CreateScreenResources; if (!(*pScreen->CreateScreenResources)(pScreen)) @@ -592,8 +592,11 @@ NVCreateScreenResources(ScreenPtr pScreen) return FALSE; if (pNv->AccelMethod == EXA) { - ppix = pScreen->GetScreenPixmap(pScreen); + PixmapPtr ppix = pScreen->GetScreenPixmap(pScreen); nouveau_bo_ref(pNv->scanout, &nouveau_pixmap(ppix)->bo); + } else + if (pNv->AccelMethod == GLAMOR) { + nouveau_glamor_create_screen_resources(pScreen); } return TRUE; @@ -1010,8 +1013,11 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) string = xf86GetOptValString(pNv->Options, OPTION_ACCELMETHOD); if (string) { - if (!strcmp(string, "none")) pNv->AccelMethod = NONE; - else if (!strcmp(string, "exa")) pNv->AccelMethod = EXA; + if (!strcmp(string, "none")) pNv->AccelMethod = NONE; + else if (!strcmp(string, "exa")) pNv->AccelMethod = EXA; +#ifdef HAVE_GLAMOR + else if (!strcmp(string, "glamor")) pNv->AccelMethod = GLAMOR; +#endif else { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Invalid AccelMethod specified\n"); @@ -1042,6 +1048,11 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) pNv->tiled_scanout = TRUE; } + if (pNv->AccelMethod == GLAMOR) { + if (!nouveau_glamor_pre_init(pScrn)) + pNv->AccelMethod = EXA; + } + pNv->ce_enabled = xf86ReturnOptValBool(pNv->Options, OPTION_ASYNC_COPY, FALSE); @@ -1413,8 +1424,14 @@ NVScreenInit(SCREEN_INIT_ARGS_DECL) xf86SetBlackWhitePixels(pScreen); - if (pNv->AccelMethod == EXA && !nouveau_exa_init(pScreen)) - return FALSE; + if (pNv->AccelMethod == GLAMOR) { + if (!nouveau_glamor_init(pScreen)) + return FALSE; + } else + if (pNv->AccelMethod == EXA) { + if (!nouveau_exa_init(pScreen)) + return FALSE; + } xf86SetBackingStore(pScreen); xf86SetSilkenMouse(pScreen); diff --git a/src/nv_type.h b/src/nv_type.h index a1133b6..263da91 100644 --- a/src/nv_type.h +++ b/src/nv_type.h @@ -49,6 +49,7 @@ typedef struct _NVRec { UNKNOWN = 0, NONE, EXA, + GLAMOR, } AccelMethod; void (*Flush)(ScrnInfoPtr); |