summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-06-19 14:54:20 +1000
committerBen Skeggs <bskeggs@redhat.com>2014-06-19 15:57:35 +1000
commit86024ceef015ffe31a204cc5bc6c326a19363ff1 (patch)
treeb9463ea3dab5f6d98ecab8604526d715bd3371c8
parentfd0ce8839f307693d86c7602dd926ce79e6b777d (diff)
glamor: initial support (no dri)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--configure.ac9
-rw-r--r--src/Makefile.am2
-rw-r--r--src/drmmode_display.c19
-rw-r--r--src/nouveau_glamor.c244
-rw-r--r--src/nouveau_glamor.h30
-rw-r--r--src/nouveau_wfb.c12
-rw-r--r--src/nouveau_xv.c5
-rw-r--r--src/nv_driver.c29
-rw-r--r--src/nv_type.h1
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);