diff options
Diffstat (limited to 'xorg-server')
92 files changed, 4966 insertions, 849 deletions
diff --git a/xorg-server/Xext/Makefile.am b/xorg-server/Xext/Makefile.am index 8e31f1367..a9a446820 100644 --- a/xorg-server/Xext/Makefile.am +++ b/xorg-server/Xext/Makefile.am @@ -1,4 +1,4 @@ -noinst_LTLIBRARIES = libXext.la +noinst_LTLIBRARIES = libXext.la libXextdpmsstubs.la AM_CFLAGS = $(DIX_CFLAGS) @@ -96,6 +96,8 @@ endif libXext_la_SOURCES = $(BUILTIN_SRCS) libXext_la_LIBADD = $(BUILTIN_LIBS) +libXextdpmsstubs_la_SOURCES = dpmsstubs.c + EXTRA_DIST = \ $(MITSHM_SRCS) \ $(XV_SRCS) \ diff --git a/xorg-server/Xi/Makefile.am b/xorg-server/Xi/Makefile.am index af85bd049..6c456c4ac 100644 --- a/xorg-server/Xi/Makefile.am +++ b/xorg-server/Xi/Makefile.am @@ -1,4 +1,4 @@ -noinst_LTLIBRARIES = libXi.la +noinst_LTLIBRARIES = libXi.la libXistubs.la AM_CFLAGS = $(DIX_CFLAGS) @@ -107,4 +107,5 @@ libXi_la_SOURCES = \ xiwarppointer.c \ xiwarppointer.h -EXTRA_DIST = stubs.c +libXistubs_la_SOURCES = \ + stubs.c diff --git a/xorg-server/composite/compext.c b/xorg-server/composite/compext.c index a945f721f..cadedbd37 100644 --- a/xorg-server/composite/compext.c +++ b/xorg-server/composite/compext.c @@ -239,6 +239,7 @@ ProcCompositeNameWindowPixmap(ClientPtr client) WindowPtr pWin; CompWindowPtr cw; PixmapPtr pPixmap; + ScreenPtr pScreen; int rc; REQUEST(xCompositeNameWindowPixmapReq); @@ -246,6 +247,8 @@ ProcCompositeNameWindowPixmap(ClientPtr client) REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq); VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess); + pScreen = pWin->drawable.pScreen; + if (!pWin->viewable) return BadMatch; @@ -255,7 +258,7 @@ ProcCompositeNameWindowPixmap(ClientPtr client) if (!cw) return BadMatch; - pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); + pPixmap = (*pScreen->GetWindowPixmap) (pWin); if (!pPixmap) return BadMatch; @@ -270,6 +273,14 @@ ProcCompositeNameWindowPixmap(ClientPtr client) if (!AddResource(stuff->pixmap, RT_PIXMAP, (void *) pPixmap)) return BadAlloc; + if (pScreen->NameWindowPixmap) { + rc = pScreen->NameWindowPixmap(pWin, pPixmap, stuff->pixmap); + if (rc != Success) { + FreeResource(stuff->pixmap, RT_NONE); + return rc; + } + } + return Success; } diff --git a/xorg-server/composite/compinit.c b/xorg-server/composite/compinit.c index 1db9e0bf5..48e938fac 100644 --- a/xorg-server/composite/compinit.c +++ b/xorg-server/composite/compinit.c @@ -229,6 +229,28 @@ CompositeRegisterAlternateVisuals(ScreenPtr pScreen, VisualID * vids, return compRegisterAlternateVisuals(cs, vids, nVisuals); } +Bool +CompositeRegisterImplicitRedirectionException(ScreenPtr pScreen, + VisualID parentVisual, + VisualID winVisual) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + CompImplicitRedirectException *p; + + p = realloc(cs->implicitRedirectExceptions, + sizeof(p[0]) * (cs->numImplicitRedirectExceptions + 1)); + if (p == NULL) + return FALSE; + + p[cs->numImplicitRedirectExceptions].parentVisual = parentVisual; + p[cs->numImplicitRedirectExceptions].winVisual = winVisual; + + cs->implicitRedirectExceptions = p; + cs->numImplicitRedirectExceptions++; + + return TRUE; +} + typedef struct _alternateVisual { int depth; CARD32 format; @@ -349,6 +371,8 @@ compScreenInit(ScreenPtr pScreen) cs->numAlternateVisuals = 0; cs->alternateVisuals = NULL; + cs->numImplicitRedirectExceptions = 0; + cs->implicitRedirectExceptions = NULL; if (!compAddAlternateVisuals(pScreen, cs)) { free(cs); diff --git a/xorg-server/composite/compint.h b/xorg-server/composite/compint.h index 12dc8b3f7..56b76c540 100644 --- a/xorg-server/composite/compint.h +++ b/xorg-server/composite/compint.h @@ -119,6 +119,11 @@ typedef struct _CompOverlayClientRec { XID resource; } CompOverlayClientRec; +typedef struct _CompImplicitRedirectException { + XID parentVisual; + XID winVisual; +} CompImplicitRedirectException; + typedef struct _CompScreen { PositionWindowProcPtr PositionWindow; CopyWindowProcPtr CopyWindow; @@ -155,6 +160,8 @@ typedef struct _CompScreen { CloseScreenProcPtr CloseScreen; int numAlternateVisuals; VisualID *alternateVisuals; + int numImplicitRedirectExceptions; + CompImplicitRedirectException *implicitRedirectExceptions; WindowPtr pOverlayWin; Window overlayWid; diff --git a/xorg-server/composite/compositeext.h b/xorg-server/composite/compositeext.h index 0b148f029..b96cb1d68 100644 --- a/xorg-server/composite/compositeext.h +++ b/xorg-server/composite/compositeext.h @@ -35,6 +35,10 @@ extern _X_EXPORT Bool CompositeRegisterAlternateVisuals(ScreenPtr pScreen, VisualID * vids, int nVisuals); +extern _X_EXPORT Bool CompositeRegisterImplicitRedirectionException(ScreenPtr pScreen, + VisualID parentVisual, + VisualID winVisual); + extern _X_EXPORT RESTYPE CompositeClientWindowType; #endif /* _COMPOSITEEXT_H_ */ diff --git a/xorg-server/composite/compwindow.c b/xorg-server/composite/compwindow.c index 6c2434959..882429414 100644 --- a/xorg-server/composite/compwindow.c +++ b/xorg-server/composite/compwindow.c @@ -336,6 +336,21 @@ compIsAlternateVisual(ScreenPtr pScreen, XID visual) } static Bool +compIsImplicitRedirectException(ScreenPtr pScreen, + XID parentVisual, XID winVisual) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + int i; + + for (i = 0; i < cs->numImplicitRedirectExceptions; i++) + if (cs->implicitRedirectExceptions[i].parentVisual == parentVisual && + cs->implicitRedirectExceptions[i].winVisual == winVisual) + return TRUE; + + return FALSE; +} + +static Bool compImplicitRedirect(WindowPtr pWin, WindowPtr pParent) { if (pParent) { @@ -343,6 +358,9 @@ compImplicitRedirect(WindowPtr pWin, WindowPtr pParent) XID winVisual = wVisual(pWin); XID parentVisual = wVisual(pParent); + if (compIsImplicitRedirectException(pScreen, parentVisual, winVisual)) + return FALSE; + if (winVisual != parentVisual && (compIsAlternateVisual(pScreen, winVisual) || compIsAlternateVisual(pScreen, parentVisual))) diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac index a75ba8f69..695a4819a 100644 --- a/xorg-server/configure.ac +++ b/xorg-server/configure.ac @@ -26,9 +26,9 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.60) -AC_INIT([xorg-server], 1.15.99.901, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server) -RELEASE_DATE="2014-02-24" -RELEASE_NAME="Szechuan Hot Pot" +AC_INIT([xorg-server], 1.15.99.902, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server) +RELEASE_DATE="2014-04-08" +RELEASE_NAME="Glacier Blue" AC_CONFIG_SRCDIR([Makefile.am]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) @@ -624,8 +624,8 @@ AC_ARG_ENABLE(clientids, AS_HELP_STRING([--disable-clientids], [Build Xorg AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=yes]) AC_ARG_ENABLE(linux_acpi, AS_HELP_STRING([--disable-linux-acpi], [Disable building ACPI support on Linux (if available).]), [enable_linux_acpi=$enableval], [enable_linux_acpi=yes]) AC_ARG_ENABLE(linux_apm, AS_HELP_STRING([--disable-linux-apm], [Disable building APM support on Linux (if available).]), [enable_linux_apm=$enableval], [enable_linux_apm=yes]) -AC_ARG_ENABLE(systemd-logind, AC_HELP_STRING([--enable-systemd-logind], [Build systemd-logind support (default: auto)]), [SYSTEMD_LOGIND=$enableval], [SYSTEMD_LOGIND=auto]) -AC_ARG_ENABLE(suid-wrapper, AC_HELP_STRING([--enable-suid-wrapper], [Build suid-root wrapper for legacy driver support on rootless xserver systems (default: no)]), [SUID_WRAPPER=$enableval], [SUID_WRAPPER=no]) +AC_ARG_ENABLE(systemd-logind, AS_HELP_STRING([--enable-systemd-logind], [Build systemd-logind support (default: auto)]), [SYSTEMD_LOGIND=$enableval], [SYSTEMD_LOGIND=auto]) +AC_ARG_ENABLE(suid-wrapper, AS_HELP_STRING([--enable-suid-wrapper], [Build suid-root wrapper for legacy driver support on rootless xserver systems (default: no)]), [SUID_WRAPPER=$enableval], [SUID_WRAPPER=no]) dnl DDXes. AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto]) @@ -633,6 +633,7 @@ AC_ARG_ENABLE(dmx, AS_HELP_STRING([--enable-dmx], [Build DMX server (d AC_ARG_ENABLE(xvfb, AS_HELP_STRING([--enable-xvfb], [Build Xvfb server (default: yes)]), [XVFB=$enableval], [XVFB=yes]) AC_ARG_ENABLE(xnest, AS_HELP_STRING([--enable-xnest], [Build Xnest server (default: auto)]), [XNEST=$enableval], [XNEST=auto]) AC_ARG_ENABLE(xquartz, AS_HELP_STRING([--enable-xquartz], [Build Xquartz server for OS-X (default: auto)]), [XQUARTZ=$enableval], [XQUARTZ=auto]) +AC_ARG_ENABLE(xwayland, AS_HELP_STRING([--enable-xwayland], [Build Xwayland server (default: auto)]), [XWAYLAND=$enableval], [XWAYLAND=auto]) AC_ARG_ENABLE(standalone-xpbproxy, AS_HELP_STRING([--enable-standalone-xpbproxy], [Build a standalone xpbproxy (in addition to the one integrated into Xquartz as a separate thread) (default: no)]), [STANDALONE_XPBPROXY=$enableval], [STANDALONE_XPBPROXY=no]) AC_ARG_ENABLE(xwin, AS_HELP_STRING([--enable-xwin], [Build XWin server (default: auto)]), [XWIN=$enableval], [XWIN=auto]) AC_ARG_ENABLE(glamor, AS_HELP_STRING([--enable-glamor], [Build glamor dix module (default: no)]), [GLAMOR=$enableval], [GLAMOR=no]) @@ -751,6 +752,7 @@ case $host_os in XQUARTZ=yes XVFB=no XNEST=no + XWAYLAND=no COMPOSITE=no DGA=no @@ -2042,7 +2044,9 @@ if test "x$XORG" = xyes; then XF86CONFIGDIR="xorg.conf.d" AC_SUBST(XF86CONFIGDIR) CONFIGFILE="$sysconfdir/$XF86CONFIGFILE" - LOGPREFIX="$logdir/Xorg." + LOGPREFIX="Xorg." + XDG_DATA_HOME=".local/share" + XDG_DATA_HOME_LOGDIR="xorg" AC_DEFINE(XORG_SERVER, 1, [Building Xorg server]) AC_DEFINE(XORGSERVER, 1, [Building Xorg server]) AC_DEFINE(XFree86Server, 1, [Building XFree86 server]) @@ -2055,7 +2059,10 @@ if test "x$XORG" = xyes; then AC_DEFINE_DIR(__XCONFIGDIR__, XF86CONFIGDIR, [Name of configuration directory]) AC_DEFINE_DIR(DEFAULT_MODULE_PATH, moduledir, [Default module search path]) AC_DEFINE_DIR(DEFAULT_LIBRARY_PATH, libdir, [Default library install path]) - AC_DEFINE_DIR(DEFAULT_LOGPREFIX, LOGPREFIX, [Default log location]) + AC_DEFINE_DIR(DEFAULT_LOGDIR, logdir, [Default log location]) + AC_DEFINE_DIR(DEFAULT_LOGPREFIX, LOGPREFIX, [Default logfile prefix]) + AC_DEFINE_DIR(DEFAULT_XDG_DATA_HOME, XDG_DATA_HOME, [Default XDG_DATA dir under HOME]) + AC_DEFINE_DIR(DEFAULT_XDG_DATA_HOME_LOGDIR, XDG_DATA_HOME_LOGDIR, [Default log dir under XDG_DATA_HOME]) AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support]) if test "x$VGAHW" = xyes; then AC_DEFINE(WITH_VGAHW, 1, [Building vgahw module]) @@ -2408,8 +2415,7 @@ if test "$KDRIVE" = yes; then fi ;; esac - KDRIVE_STUB_LIB='$(top_builddir)/hw/kdrive/src/libkdrivestubs.la' - KDRIVE_LOCAL_LIBS="$MAIN_LIB $DIX_LIB $KDRIVE_LIB $KDRIVE_STUB_LIB" + KDRIVE_LOCAL_LIBS="$MAIN_LIB $DIX_LIB $KDRIVE_LIB" KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $FB_LIB $MI_LIB $KDRIVE_PURE_LIBS" KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $KDRIVE_OS_LIB" KDRIVE_LIBS="$KDRIVE_LOCAL_LIBS $XSERVER_SYS_LIBS $GLX_SYS_LIBS $DLOPEN_LIBS $TSLIB_LIBS" @@ -2433,6 +2439,29 @@ AM_CONDITIONAL(XEPHYR, [test "x$KDRIVE" = xyes && test "x$XEPHYR" = xyes]) AM_CONDITIONAL(BUILD_KDRIVEFBDEVLIB, [test "x$KDRIVE" = xyes && test "x$KDRIVEFBDEVLIB" = xyes]) AM_CONDITIONAL(XFAKESERVER, [test "x$KDRIVE" = xyes && test "x$XFAKE" = xyes]) +dnl Xwayland DDX + +PKG_CHECK_MODULES(XWAYLANDMODULES, [wayland-client libdrm epoxy], [have_xwayland=yes], [have_xwayland=no]) +AC_MSG_CHECKING([whether to build Xwayland DDX]) +if test "x$XWAYLAND" = xauto; then + XWAYLAND="$have_xwayland" +fi +AC_MSG_RESULT([$XWAYLAND]) +AM_CONDITIONAL(XWAYLAND, [test "x$XWAYLAND" = xyes]) + +if test "x$XWAYLAND" = xyes; then + if test "x$have_xwayland" = xno; then + AC_MSG_ERROR([Xwayland build explicitly requested, but required modules not found.]) + fi + + XWAYLAND_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB" + XWAYLAND_SYS_LIBS="$XWAYLANDMODULES_LIBS $GLX_SYS_LIBS" + AC_SUBST([XWAYLAND_LIBS]) + AC_SUBST([XWAYLAND_SYS_LIBS]) + WAYLAND_SCANNER_RULES(['$(top_srcdir)/hw/xwayland']) +fi + + dnl and the rest of these are generic, so they're in config.h dnl dnl though, thanks to the passing of some significant amount of time, the @@ -2575,6 +2604,7 @@ hw/kdrive/fake/Makefile hw/kdrive/fbdev/Makefile hw/kdrive/linux/Makefile hw/kdrive/src/Makefile +hw/xwayland/Makefile test/Makefile test/xi2/Makefile xserver.ent diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c index f05dada3d..125a0ee29 100644 --- a/xorg-server/dix/events.c +++ b/xorg-server/dix/events.c @@ -2835,7 +2835,7 @@ DeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent) return deliveries; } -static Bool +Bool PointInBorderSize(WindowPtr pWin, int x, int y) { BoxRec box; @@ -2876,49 +2876,9 @@ PointInBorderSize(WindowPtr pWin, int x, int y) WindowPtr XYToWindow(SpritePtr pSprite, int x, int y) { - WindowPtr pWin; - BoxRec box; + ScreenPtr pScreen = RootWindow(pSprite)->drawable.pScreen; - pSprite->spriteTraceGood = 1; /* root window still there */ - pWin = RootWindow(pSprite)->firstChild; - while (pWin) { - if ((pWin->mapped) && - (x >= pWin->drawable.x - wBorderWidth(pWin)) && - (x < pWin->drawable.x + (int) pWin->drawable.width + - wBorderWidth(pWin)) && - (y >= pWin->drawable.y - wBorderWidth(pWin)) && - (y < pWin->drawable.y + (int) pWin->drawable.height + - wBorderWidth(pWin)) - /* When a window is shaped, a further check - * is made to see if the point is inside - * borderSize - */ - && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y)) - && (!wInputShape(pWin) || - RegionContainsPoint(wInputShape(pWin), - x - pWin->drawable.x, - y - pWin->drawable.y, &box)) -#ifdef ROOTLESS - /* In rootless mode windows may be offscreen, even when - * they're in X's stack. (E.g. if the native window system - * implements some form of virtual desktop system). - */ - && !pWin->rootlessUnhittable -#endif - ) { - if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) { - pSprite->spriteTraceSize += 10; - pSprite->spriteTrace = realloc(pSprite->spriteTrace, - pSprite->spriteTraceSize * - sizeof(WindowPtr)); - } - pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin; - pWin = pWin->firstChild; - } - else - pWin = pWin->nextSib; - } - return DeepestSpriteWin(pSprite); + return (*pScreen->XYToWindow)(pScreen, pSprite, x, y); } /** diff --git a/xorg-server/dix/globals.c b/xorg-server/dix/globals.c index 9738e9cdf..eaa2afe24 100644 --- a/xorg-server/dix/globals.c +++ b/xorg-server/dix/globals.c @@ -127,7 +127,8 @@ int defaultColorVisualClass = -1; int monitorResolution = 0; const char *display; -int displayfd; +int displayfd = -1; +Bool explicit_display = FALSE; char *ConnectionInfo; CARD32 TimeOutValue = DEFAULT_TIMEOUT * MILLI_PER_SECOND; diff --git a/xorg-server/dri3/dri3.h b/xorg-server/dri3/dri3.h index 7c0c33018..edc7fa267 100644 --- a/xorg-server/dri3/dri3.h +++ b/xorg-server/dri3/dri3.h @@ -30,12 +30,17 @@ #include <X11/extensions/dri3proto.h> #include <randrstr.h> -#define DRI3_SCREEN_INFO_VERSION 0 +#define DRI3_SCREEN_INFO_VERSION 1 typedef int (*dri3_open_proc)(ScreenPtr screen, RRProviderPtr provider, int *fd); +typedef int (*dri3_open_client_proc)(ClientPtr client, + ScreenPtr screen, + RRProviderPtr provider, + int *fd); + typedef PixmapPtr (*dri3_pixmap_from_fd_proc) (ScreenPtr screen, int fd, CARD16 width, @@ -55,11 +60,18 @@ typedef struct dri3_screen_info { dri3_open_proc open; dri3_pixmap_from_fd_proc pixmap_from_fd; dri3_fd_from_pixmap_proc fd_from_pixmap; + + /* Version 1 */ + dri3_open_client_proc open_client; + } dri3_screen_info_rec, *dri3_screen_info_ptr; extern _X_EXPORT Bool dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info); +extern _X_EXPORT int +dri3_send_open_reply(ClientPtr client, int fd); + #endif #endif /* _DRI3_H_ */ diff --git a/xorg-server/dri3/dri3_request.c b/xorg-server/dri3/dri3_request.c index 31dce83f6..fe45620c9 100644 --- a/xorg-server/dri3/dri3_request.c +++ b/xorg-server/dri3/dri3_request.c @@ -55,16 +55,35 @@ proc_dri3_query_version(ClientPtr client) return Success; } -static int -proc_dri3_open(ClientPtr client) +int +dri3_send_open_reply(ClientPtr client, int fd) { - REQUEST(xDRI3OpenReq); xDRI3OpenReply rep = { .type = X_Reply, .nfd = 1, .sequenceNumber = client->sequence, .length = 0, }; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + } + + if (WriteFdToClient(client, fd, TRUE) < 0) { + close(fd); + return BadAlloc; + } + + WriteToClient(client, sizeof (rep), &rep); + + return Success; +} + +static int +proc_dri3_open(ClientPtr client) +{ + REQUEST(xDRI3OpenReq); RRProviderPtr provider; DrawablePtr drawable; ScreenPtr screen; @@ -92,17 +111,8 @@ proc_dri3_open(ClientPtr client) if (status != Success) return status; - if (client->swapped) { - swaps(&rep.sequenceNumber); - swapl(&rep.length); - } - - if (WriteFdToClient(client, fd, TRUE) < 0) { - close(fd); - return BadAlloc; - } - - WriteToClient(client, sizeof (rep), &rep); + if (client->ignoreCount == 0) + return dri3_send_open_reply(client, fd); return Success; } diff --git a/xorg-server/dri3/dri3_screen.c b/xorg-server/dri3/dri3_screen.c index c88029612..6c0c60cbf 100644 --- a/xorg-server/dri3/dri3_screen.c +++ b/xorg-server/dri3/dri3_screen.c @@ -30,6 +30,14 @@ #include <misyncshm.h> #include <randrstr.h> +static inline Bool has_open(dri3_screen_info_ptr info) { + if (info == NULL) + return FALSE; + + return info->open != NULL || + (info->version >= 1 && info->open_client != NULL); +} + int dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd) { @@ -37,10 +45,14 @@ dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd) dri3_screen_info_ptr info = ds->info; int rc; - if (!info || !info->open) + if (!has_open(info)) return BadMatch; - rc = (*info->open) (screen, provider, fd); + if (info->version >= 1 && info->open_client != NULL) + rc = (*info->open_client) (client, screen, provider, fd); + else + rc = (*info->open) (screen, provider, fd); + if (rc != Success) return rc; diff --git a/xorg-server/fb/Makefile.am b/xorg-server/fb/Makefile.am index 89f3babb1..752eabeb7 100644 --- a/xorg-server/fb/Makefile.am +++ b/xorg-server/fb/Makefile.am @@ -22,6 +22,7 @@ libfb_la_SOURCES = \ fbbits.h \ fbblt.c \ fbbltone.c \ + fbcmap_mi.c \ fbcopy.c \ fbfill.c \ fbfillrect.c \ @@ -50,5 +51,3 @@ libfb_la_SOURCES = \ fbwindow.c libwfb_la_SOURCES = $(libfb_la_SOURCES) - -EXTRA_DIST = fbcmap_mi.c diff --git a/xorg-server/fb/fbpict.c b/xorg-server/fb/fbpict.c index b50385805..c2ee8a552 100644 --- a/xorg-server/fb/fbpict.c +++ b/xorg-server/fb/fbpict.c @@ -82,7 +82,7 @@ fbDestroyGlyphCache(void) } } -static void +void fbUnrealizeGlyph(ScreenPtr pScreen, GlyphPtr pGlyph) { @@ -90,7 +90,7 @@ fbUnrealizeGlyph(ScreenPtr pScreen, pixman_glyph_cache_remove (glyphCache, pGlyph, NULL); } -static void +void fbGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, diff --git a/xorg-server/fb/fbpict.h b/xorg-server/fb/fbpict.h index 110f32dfe..8b0f59f7a 100644 --- a/xorg-server/fb/fbpict.h +++ b/xorg-server/fb/fbpict.h @@ -65,11 +65,24 @@ fbTrapezoids(CARD8 op, INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid * traps); extern _X_EXPORT void - fbTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int ntris, xTriangle * tris); +extern _X_EXPORT void +fbUnrealizeGlyph(ScreenPtr pScreen, + GlyphPtr pGlyph); + +extern _X_EXPORT void +fbGlyphs(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, int nlist, + GlyphListPtr list, + GlyphPtr *glyphs); + #endif /* _FBPICT_H_ */ diff --git a/xorg-server/glamor/Makefile.am b/xorg-server/glamor/Makefile.am index 8555e4087..4d0cc8138 100644 --- a/xorg-server/glamor/Makefile.am +++ b/xorg-server/glamor/Makefile.am @@ -12,18 +12,20 @@ libglamor_la_SOURCES = \ glamor_core.c \ glamor_debug.h \ glamor_fill.c \ - glamor_fillspans.c \ - glamor_getspans.c \ + glamor_font.c \ glamor_glx.c \ glamor_glyphs.c \ - glamor_polyfillrect.c \ glamor_polylines.c \ glamor_putimage.c \ - glamor_setspans.c \ glamor_segment.c \ glamor_render.c \ glamor_gradient.c \ glamor_program.c \ + glamor_rects.c \ + glamor_spans.c \ + glamor_text.c \ + glamor_transfer.c \ + glamor_transfer.h \ glamor_transform.c \ glamor_trapezoid.c \ glamor_tile.c \ diff --git a/xorg-server/glamor/glamor.c b/xorg-server/glamor/glamor.c index 30944326b..2c2d9760c 100644 --- a/xorg-server/glamor/glamor.c +++ b/xorg-server/glamor/glamor.c @@ -182,7 +182,15 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3; screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL); - if (type == GLAMOR_MEMORY_MAP || usage == GLAMOR_CREATE_NO_LARGE || + if (usage == GLAMOR_CREATE_PIXMAP_NO_TEXTURE) { + pixmap_priv->type = GLAMOR_TEXTURE_ONLY; + pixmap_priv->base.box.x1 = 0; + pixmap_priv->base.box.y1 = 0; + pixmap_priv->base.box.x2 = w; + pixmap_priv->base.box.y2 = h; + return pixmap; + } + else if (type == GLAMOR_MEMORY_MAP || usage == GLAMOR_CREATE_NO_LARGE || glamor_check_fbo_size(glamor_priv, w, h)) { pixmap_priv->type = type; @@ -353,6 +361,15 @@ glamor_init(ScreenPtr screen, unsigned int flags) gl_version = epoxy_gl_version(); + /* Would be nice to have a cleaner test for GLSL 1.30 support, + * but for now this should suffice + */ + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && gl_version >= 30) + glamor_priv->glsl_version = 130; + else + glamor_priv->glsl_version = 120; + + /* We'd like to require GL_ARB_map_buffer_range or * GL_OES_map_buffer_range, since it offers more information to * the driver than plain old glMapBuffer() or glBufferSubData(). @@ -415,6 +432,9 @@ glamor_init(ScreenPtr screen, unsigned int flags) screen->CreateScreenResources; screen->CreateScreenResources = glamor_create_screen_resources; + if (!glamor_font_init(screen)) + goto fail; + if (flags & GLAMOR_USE_SCREEN) { if (!RegisterBlockAndWakeupHandlers(_glamor_block_handler, _glamor_wakeup_handler, @@ -475,13 +495,13 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_priv->saved_procs.create_picture = ps->CreatePicture; ps->CreatePicture = glamor_create_picture; - glamor_priv->saved_procs.set_window_pixmap = screen->SetWindowPixmap; - screen->SetWindowPixmap = glamor_set_window_pixmap; - glamor_priv->saved_procs.destroy_picture = ps->DestroyPicture; ps->DestroyPicture = glamor_destroy_picture; glamor_init_composite_shaders(screen); #endif + glamor_priv->saved_procs.set_window_pixmap = screen->SetWindowPixmap; + screen->SetWindowPixmap = glamor_set_window_pixmap; + glamor_init_vbo(screen); glamor_init_pixmap_fbo(screen); glamor_init_solid_shader(screen); @@ -494,9 +514,6 @@ glamor_init(ScreenPtr screen, unsigned int flags) #ifdef GLAMOR_GRADIENT_SHADER glamor_init_gradient_shader(screen); #endif -#ifdef GLAMOR_XV - glamor_init_xv_shader(screen); -#endif glamor_pixmap_init(screen); glamor_glyphs_init(screen); @@ -516,9 +533,6 @@ glamor_release_screen_priv(ScreenPtr screen) glamor_screen_private *glamor_priv; glamor_priv = glamor_get_screen_private(screen); -#ifdef GLAMOR_XV - glamor_fini_xv_shader(screen); -#endif #ifdef RENDER glamor_fini_composite_shaders(screen); #endif diff --git a/xorg-server/glamor/glamor.h b/xorg-server/glamor/glamor.h index 11ec49361..e63762b44 100644 --- a/xorg-server/glamor/glamor.h +++ b/xorg-server/glamor/glamor.h @@ -143,12 +143,14 @@ extern _X_EXPORT void glamor_block_handler(ScreenPtr screen); extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned int usage); +extern _X_EXPORT Bool glamor_destroy_pixmap(PixmapPtr pixmap); #define GLAMOR_CREATE_PIXMAP_CPU 0x100 #define GLAMOR_CREATE_PIXMAP_FIXUP 0x101 #define GLAMOR_CREATE_FBO_NO_FBO 0x103 #define GLAMOR_CREATE_PIXMAP_MAP 0x104 #define GLAMOR_CREATE_NO_LARGE 0x105 +#define GLAMOR_CREATE_PIXMAP_NO_TEXTURE 0x106 /* @glamor_egl_exchange_buffers: Exchange the underlying buffers(KHR image,fbo). * @@ -310,6 +312,8 @@ extern _X_EXPORT Bool #endif +extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen, + struct glamor_context *glamor_ctx); extern _X_EXPORT void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap); extern _X_EXPORT int glamor_create_gc(GCPtr gc); @@ -431,12 +435,23 @@ extern _X_EXPORT Bool glamor_poly_point_nf(DrawablePtr pDrawable, GCPtr pGC, extern _X_EXPORT Bool glamor_poly_segment_nf(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSeg); -extern _X_EXPORT Bool glamor_poly_line_nf(DrawablePtr pDrawable, GCPtr pGC, - int mode, int npt, DDXPointPtr ppt); - extern _X_EXPORT Bool glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc, int mode, int n, DDXPointPtr points); +extern _X_EXPORT Bool glamor_poly_text8_nf(DrawablePtr drawable, GCPtr gc, + int x, int y, int count, char *chars, int *final_pos); + +extern _X_EXPORT Bool glamor_poly_text16_nf(DrawablePtr drawable, GCPtr gc, + int x, int y, int count, unsigned short *chars, int *final_pos); + +extern _X_EXPORT Bool glamor_image_text8_nf(DrawablePtr drawable, GCPtr gc, + int x, int y, int count, char *chars); + +extern _X_EXPORT Bool glamor_image_text16_nf(DrawablePtr drawable, GCPtr gc, + int x, int y, int count, unsigned short *chars); + +#define HAS_GLAMOR_TEXT 1 + #ifdef GLAMOR_FOR_XORG extern _X_EXPORT XF86VideoAdaptorPtr glamor_xv_init(ScreenPtr pScreen, int num_texture_ports); diff --git a/xorg-server/glamor/glamor_core.c b/xorg-server/glamor/glamor_core.c index 5711be72f..7b1615d2d 100644 --- a/xorg-server/glamor/glamor_core.c +++ b/xorg-server/glamor/glamor_core.c @@ -426,13 +426,13 @@ GCOps glamor_gc_ops = { .FillPolygon = miFillPolygon, .PolyFillRect = glamor_poly_fill_rect, .PolyFillArc = miPolyFillArc, - .PolyText8 = miPolyText8, - .PolyText16 = miPolyText16, - .ImageText8 = miImageText8, - .ImageText16 = miImageText16, - .ImageGlyphBlt = glamor_image_glyph_blt, //miImageGlyphBlt, - .PolyGlyphBlt = glamor_poly_glyph_blt, //miPolyGlyphBlt, - .PushPixels = glamor_push_pixels, //miPushPixels, + .PolyText8 = glamor_poly_text8, + .PolyText16 = glamor_poly_text16, + .ImageText8 = glamor_image_text8, + .ImageText16 = glamor_image_text16, + .ImageGlyphBlt = miImageGlyphBlt, + .PolyGlyphBlt = glamor_poly_glyph_blt, + .PushPixels = glamor_push_pixels, }; /** diff --git a/xorg-server/glamor/glamor_egl.c b/xorg-server/glamor/glamor_egl.c index 812342129..d37de9b95 100644 --- a/xorg-server/glamor/glamor_egl.c +++ b/xorg-server/glamor/glamor_egl.c @@ -608,9 +608,10 @@ glamor_egl_close_screen(ScreenPtr screen) } static int -glamor_dri3_open(ScreenPtr screen, - RRProviderPtr provider, - int *fdp) +glamor_dri3_open_client(ClientPtr client, + ScreenPtr screen, + RRProviderPtr provider, + int *fdp) { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl = @@ -657,8 +658,8 @@ glamor_dri3_open(ScreenPtr screen, } static dri3_screen_info_rec glamor_dri3_info = { - .version = 0, - .open = glamor_dri3_open, + .version = 1, + .open_client = glamor_dri3_open_client, .pixmap_from_fd = glamor_pixmap_from_fd, .fd_from_pixmap = glamor_fd_from_pixmap, }; diff --git a/xorg-server/glamor/glamor_egl_stubs.c b/xorg-server/glamor/glamor_egl_stubs.c index 4fd9e8016..028d1cc05 100644 --- a/xorg-server/glamor/glamor_egl_stubs.c +++ b/xorg-server/glamor/glamor_egl_stubs.c @@ -26,7 +26,9 @@ * Stubbed out glamor_egl.c functions for servers other than Xorg. */ -#include "glamor_priv.h" +#include "dix-config.h" + +#include "glamor.h" void glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx) diff --git a/xorg-server/glamor/glamor_fillspans.c b/xorg-server/glamor/glamor_fillspans.c deleted file mode 100644 index 8cbd79f6d..000000000 --- a/xorg-server/glamor/glamor_fillspans.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright © 1998 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/** @file glamor_fillspans.c - * - * FillSpans implementation, taken from fb_fillsp.c - */ -#include "glamor_priv.h" - -static Bool -_glamor_fill_spans(DrawablePtr drawable, - GCPtr gc, - int n, DDXPointPtr points, int *widths, int sorted, - Bool fallback) -{ - DDXPointPtr ppt; - int nbox; - BoxPtr pbox; - int x1, x2, y; - RegionPtr pClip = fbGetCompositeClip(gc); - Bool ret = FALSE; - - if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) - goto fail; - - ppt = points; - while (n--) { - x1 = ppt->x; - y = ppt->y; - x2 = x1 + (int) *widths; - ppt++; - widths++; - - nbox = REGION_NUM_RECTS(pClip); - pbox = REGION_RECTS(pClip); - while (nbox--) { - int real_x1 = x1, real_x2 = x2; - - if (real_x1 < pbox->x1) - real_x1 = pbox->x1; - - if (real_x2 > pbox->x2) - real_x2 = pbox->x2; - - if (real_x2 > real_x1 && pbox->y1 <= y && pbox->y2 > y) { - if (!glamor_fill(drawable, gc, real_x1, y, - real_x2 - real_x1, 1, fallback)) - goto fail; - } - pbox++; - } - } - ret = TRUE; - goto done; - - fail: - if (!fallback && glamor_ddx_fallback_check_pixmap(drawable) - && glamor_ddx_fallback_check_gc(gc)) { - goto done; - } - glamor_fallback("to %p (%c)\n", drawable, - glamor_get_drawable_location(drawable)); - if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && - glamor_prepare_access_gc(gc)) { - fbFillSpans(drawable, gc, n, points, widths, sorted); - } - glamor_finish_access_gc(gc); - glamor_finish_access(drawable); - ret = TRUE; - - done: - return ret; -} - -void -glamor_fill_spans(DrawablePtr drawable, - GCPtr gc, int n, DDXPointPtr points, int *widths, int sorted) -{ - _glamor_fill_spans(drawable, gc, n, points, widths, sorted, TRUE); -} - -Bool -glamor_fill_spans_nf(DrawablePtr drawable, - GCPtr gc, - int n, DDXPointPtr points, int *widths, int sorted) -{ - return _glamor_fill_spans(drawable, gc, n, points, widths, sorted, FALSE); -} diff --git a/xorg-server/glamor/glamor_font.c b/xorg-server/glamor/glamor_font.c new file mode 100644 index 000000000..47dfe2a69 --- /dev/null +++ b/xorg-server/glamor/glamor_font.c @@ -0,0 +1,186 @@ +/* + * Copyright © 2014 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "glamor_priv.h" +#include "glamor_font.h" +#include <dixfontstr.h> + +static int glamor_font_generation; +static int glamor_font_private_index; +static int glamor_font_screen_count; + +glamor_font_t * +glamor_font_get(ScreenPtr screen, FontPtr font) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + glamor_font_t *privates; + glamor_font_t *glamor_font; + int overall_width, overall_height; + int num_rows; + int num_cols; + int glyph_width_pixels; + int glyph_width_bytes; + int glyph_height; + int row, col; + unsigned char c[2]; + CharInfoPtr glyph; + unsigned long count; + + + privates = FontGetPrivate(font, glamor_font_private_index); + if (!privates) { + privates = calloc(glamor_font_screen_count, sizeof (glamor_font_t)); + if (!privates) + return NULL; + FontSetPrivate(font, glamor_font_private_index, privates); + } + + glamor_font = &privates[screen->myNum]; + + if (glamor_font->realized) + return glamor_font; + + glamor_font->realized = TRUE; + + /* Figure out how many glyphs are in the font */ + num_cols = font->info.lastCol - font->info.firstCol + 1; + num_rows = font->info.lastRow - font->info.firstRow + 1; + + /* Figure out the size of each glyph */ + glyph_width_pixels = font->info.maxbounds.rightSideBearing - font->info.minbounds.leftSideBearing; + glyph_height = font->info.maxbounds.ascent + font->info.maxbounds.descent; + + glyph_width_bytes = (glyph_width_pixels + 7) >> 3; + + glamor_font->glyph_width_pixels = glyph_width_pixels; + glamor_font->glyph_width_bytes = glyph_width_bytes; + glamor_font->glyph_height = glyph_height; + + overall_width = glyph_width_bytes * num_cols; + overall_height = glyph_height * num_rows; + + /* Check whether the font has a default character */ + c[0] = font->info.lastRow + 1; + c[1] = font->info.lastCol + 1; + (*font->get_glyphs)(font, 1, c, TwoD16Bit, &count, &glyph); + + glamor_font->default_char = count ? glyph : NULL; + glamor_font->default_row = font->info.defaultCh >> 8; + glamor_font->default_col = font->info.defaultCh; + + glamor_priv = glamor_get_screen_private(screen); + glamor_get_context(glamor_priv); + + glGenTextures(1, &glamor_font->texture_id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, glamor_font->texture_id); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + /* Allocate storage */ + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, overall_width, overall_height, + 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + + /* Paint all of the glyphs */ + for (row = 0; row < num_rows; row++) { + for (col = 0; col < num_cols; col++) { + c[0] = row + font->info.firstRow; + c[1] = col + font->info.firstCol; + + (*font->get_glyphs)(font, 1, c, TwoD16Bit, &count, &glyph); + + if (count) + glTexSubImage2D(GL_TEXTURE_2D, 0, col * glyph_width_bytes, row * glyph_height, + GLYPHWIDTHBYTES(glyph), GLYPHHEIGHTPIXELS(glyph), + GL_RED_INTEGER, GL_UNSIGNED_BYTE, glyph->bits); + } + } + + glamor_put_context(glamor_priv); + + return glamor_font; +} + +static Bool +glamor_realize_font(ScreenPtr screen, FontPtr font) +{ + return TRUE; +} + +static Bool +glamor_unrealize_font(ScreenPtr screen, FontPtr font) +{ + glamor_screen_private *glamor_priv; + glamor_font_t *privates = FontGetPrivate(font, glamor_font_private_index); + glamor_font_t *glamor_font; + int s; + + if (!privates) + return TRUE; + + glamor_font = &privates[screen->myNum]; + + if (!glamor_font->realized) + return TRUE; + + /* Unrealize the font, freeing the allocated texture */ + glamor_font->realized = FALSE; + + glamor_priv = glamor_get_screen_private(screen); + glamor_get_context(glamor_priv); + glDeleteTextures(1, &glamor_font->texture_id); + glamor_put_context(glamor_priv); + + /* Check to see if all of the screens are done with this font + * and free the private when that happens + */ + for (s = 0; s < glamor_font_screen_count; s++) + if (privates[s].realized) + return TRUE; + + free(privates); + FontSetPrivate(font, glamor_font_private_index, NULL); + return TRUE; +} + +Bool +glamor_font_init(ScreenPtr screen) +{ + if (glamor_font_generation != serverGeneration) { + glamor_font_private_index = AllocateFontPrivateIndex(); + if (glamor_font_private_index == -1) + return FALSE; + glamor_font_screen_count = 0; + glamor_font_generation = serverGeneration; + } + + if (screen->myNum >= glamor_font_screen_count) + glamor_font_screen_count = screen->myNum + 1; + + screen->RealizeFont = glamor_realize_font; + screen->UnrealizeFont = glamor_unrealize_font; + return TRUE; +} diff --git a/xorg-server/glamor/glamor_font.h b/xorg-server/glamor/glamor_font.h new file mode 100644 index 000000000..36d20624d --- /dev/null +++ b/xorg-server/glamor/glamor_font.h @@ -0,0 +1,49 @@ +/* + * Copyright © 2014 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _GLAMOR_FONT_H_ +#define _GLAMOR_FONT_H_ + +typedef struct { + Bool realized; + CharInfoPtr default_char; + CARD8 default_row; + CARD8 default_col; + + GLuint texture_id; + + CARD16 glyph_width_bytes; + CARD16 glyph_width_pixels; + CARD16 glyph_height; + +} glamor_font_t; + +glamor_font_t * +glamor_font_get(ScreenPtr screen, FontPtr font); + +Bool +glamor_font_init(ScreenPtr screen); + +void +glamor_fini_glyph_shader(ScreenPtr screen); + +#endif /* _GLAMOR_FONT_H_ */ diff --git a/xorg-server/glamor/glamor_getspans.c b/xorg-server/glamor/glamor_getspans.c deleted file mode 100644 index 42df87f3d..000000000 --- a/xorg-server/glamor/glamor_getspans.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright © 2009 Intel Corporation - * - * 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 (including the next - * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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: - * Eric Anholt <eric@anholt.net> - * Zhigang Gong <zhigang.gong@linux.intel.com> - * - */ - -#include "glamor_priv.h" - -static Bool -_glamor_get_spans(DrawablePtr drawable, - int wmax, - DDXPointPtr points, int *widths, int count, char *dst, - Bool fallback) -{ - PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - int i; - uint8_t *readpixels_dst = (uint8_t *) dst; - void *data; - int x_off, y_off; - Bool ret = FALSE; - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) - goto fail; - - glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); - for (i = 0; i < count; i++) { - data = glamor_download_sub_pixmap_to_cpu(pixmap, points[i].x + x_off, - points[i].y + y_off, widths[i], - 1, PixmapBytePad(widths[i], - drawable-> - depth), - readpixels_dst, 0, - GLAMOR_ACCESS_RO); - (void)data; - assert(data == readpixels_dst); - readpixels_dst += PixmapBytePad(widths[i], drawable->depth); - } - - ret = TRUE; - goto done; - fail: - - if (!fallback && glamor_ddx_fallback_check_pixmap(drawable)) - goto done; - - ret = TRUE; - if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO)) { - fbGetSpans(drawable, wmax, points, widths, count, dst); - } - glamor_finish_access(drawable); - done: - return ret; -} - -void -glamor_get_spans(DrawablePtr drawable, - int wmax, - DDXPointPtr points, int *widths, int count, char *dst) -{ - _glamor_get_spans(drawable, wmax, points, widths, count, dst, TRUE); -} - -Bool -glamor_get_spans_nf(DrawablePtr drawable, - int wmax, - DDXPointPtr points, int *widths, int count, char *dst) -{ - return _glamor_get_spans(drawable, wmax, points, widths, count, dst, FALSE); -} diff --git a/xorg-server/glamor/glamor_glyphblt.c b/xorg-server/glamor/glamor_glyphblt.c index a58cef907..c031747f7 100644 --- a/xorg-server/glamor/glamor_glyphblt.c +++ b/xorg-server/glamor/glamor_glyphblt.c @@ -28,203 +28,156 @@ #include "glamor_priv.h" #include <dixfontstr.h> +#include "glamor_transform.h" + +static const glamor_facet glamor_facet_poly_glyph_blt = { + .name = "poly_glyph_blt", + .vs_vars = "attribute vec2 primitive;\n", + .vs_exec = (" vec2 pos = vec2(0,0);\n" + GLAMOR_POS(gl_Position, primitive)), +}; static Bool -glamor_poly_glyph_blt_pixels(DrawablePtr drawable, GCPtr gc, - int x, int y, unsigned int nglyph, - CharInfoPtr *ppci) +glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc, + int start_x, int y, unsigned int nglyph, + CharInfoPtr *ppci, void *pglyph_base) { ScreenPtr screen = drawable->pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv; - int off_x, off_y; - GLfloat xscale, yscale; - float color[4]; - unsigned long fg_pixel = gc->fgPixel; - char *vbo_offset; - RegionPtr clip; - int num_points, max_points; - float *points = NULL; - - x += drawable->x; - y += drawable->y; - - if (gc->fillStyle != FillSolid) { - glamor_fallback("gc fillstyle not solid\n"); - return FALSE; - } + glamor_program *prog; + RegionPtr clip = gc->pCompositeClip; + int box_x, box_y; pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) - return FALSE; + goto bail; glamor_get_context(glamor_priv); - if (!glamor_set_alu(screen, gc->alu)) { - if (gc->alu == GXclear) - fg_pixel = 0; - else { - glamor_fallback("unsupported alu %x\n", gc->alu); - glamor_put_context(glamor_priv); - return FALSE; - } - } - - if (!glamor_set_planemask(pixmap, gc->planemask)) { - glamor_fallback("Failed to set planemask in %s.\n", __FUNCTION__); - glamor_put_context(glamor_priv); - return FALSE; - } - - glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); - - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale); - - glUseProgram(glamor_priv->solid_prog); - glamor_get_rgba_from_pixel(fg_pixel, - &color[0], &color[1], &color[2], &color[3], - format_for_pixmap(pixmap)); - glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color); - - clip = fbGetCompositeClip(gc); + prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_glyph_blt_progs, + &glamor_facet_poly_glyph_blt); + if (!prog) + goto bail_ctx; glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - max_points = 500; - num_points = 0; - while (nglyph--) { - CharInfoPtr charinfo = *ppci++; - int w = GLYPHWIDTHPIXELS(charinfo); - int h = GLYPHHEIGHTPIXELS(charinfo); - uint8_t *glyphbits = FONTGLYPHBITS(NULL, charinfo); - - if (w && h) { - int glyph_x = x + charinfo->metrics.leftSideBearing; - int glyph_y = y - charinfo->metrics.ascent; - int glyph_stride = GLYPHWIDTHBYTESPADDED(charinfo); - int xx, yy; - - for (yy = 0; yy < h; yy++) { - uint8_t *glyph_row = glyphbits + glyph_stride * yy; - for (xx = 0; xx < w; xx++) { - int pt_x_i = glyph_x + xx; - int pt_y_i = glyph_y + yy; - float pt_x_f, pt_y_f; - if (!(glyph_row[xx / 8] & (1 << xx % 8))) - continue; - - if (!RegionContainsPoint(clip, pt_x_i, pt_y_i, NULL)) - continue; - - if (!num_points) { - points = glamor_get_vbo_space(screen, - max_points * 2 * sizeof(float), - &vbo_offset); - - glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), - vbo_offset); - } - - pt_x_f = v_from_x_coord_x(xscale, pt_x_i + off_x + 0.5); - if (glamor_priv->yInverted) - pt_y_f = v_from_x_coord_y_inverted(yscale, pt_y_i + off_y + 0.5); - else - pt_y_f = v_from_x_coord_y(yscale, pt_y_i + off_y + 0.5); - - points[num_points * 2 + 0] = pt_x_f; - points[num_points * 2 + 1] = pt_y_f; - num_points++; + start_x += drawable->x; + y += drawable->y; - if (num_points == max_points) { - glamor_put_vbo_space(screen); - glDrawArrays(GL_POINTS, 0, num_points); - num_points = 0; + glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + int x; + int n; + int num_points, max_points; + INT16 *points = NULL; + int off_x, off_y; + char *vbo_offset; + + glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, TRUE, prog->matrix_uniform, &off_x, &off_y); + + max_points = 500; + num_points = 0; + x = start_x; + for (n = 0; n < nglyph; n++) { + CharInfoPtr charinfo = ppci[n]; + int w = GLYPHWIDTHPIXELS(charinfo); + int h = GLYPHHEIGHTPIXELS(charinfo); + uint8_t *glyphbits = FONTGLYPHBITS(NULL, charinfo); + + if (w && h) { + int glyph_x = x + charinfo->metrics.leftSideBearing; + int glyph_y = y - charinfo->metrics.ascent; + int glyph_stride = GLYPHWIDTHBYTESPADDED(charinfo); + int xx, yy; + + for (yy = 0; yy < h; yy++) { + uint8_t *glyph = glyphbits; + for (xx = 0; xx < w; glyph += ((xx&7) == 7), xx++) { + int pt_x_i = glyph_x + xx; + int pt_y_i = glyph_y + yy; + + if (!(*glyph & (1 << (xx & 7)))) + continue; + + if (!RegionContainsPoint(clip, pt_x_i, pt_y_i, NULL)) + continue; + + if (!num_points) { + points = glamor_get_vbo_space(screen, + max_points * (2 * sizeof (INT16)), + &vbo_offset); + + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, + GL_FALSE, 0, vbo_offset); + } + + *points++ = pt_x_i; + *points++ = pt_y_i; + num_points++; + + if (num_points == max_points) { + glamor_put_vbo_space(screen); + glDrawArrays(GL_POINTS, 0, num_points); + num_points = 0; + } } + glyphbits += glyph_stride; } } + x += charinfo->metrics.characterWidth; } - x += charinfo->metrics.characterWidth; - } - - if (num_points) { - glamor_put_vbo_space(screen); - glDrawArrays(GL_POINTS, 0, num_points); + if (num_points) { + glamor_put_vbo_space(screen); + glDrawArrays(GL_POINTS, 0, num_points); + } } + glDisable(GL_COLOR_LOGIC_OP); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); glamor_put_context(glamor_priv); - - return TRUE; -} - -static Bool -_glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, unsigned int nglyph, - CharInfoPtr *ppci, void *pglyphBase, Bool fallback) -{ - if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable) - && glamor_ddx_fallback_check_gc(pGC)) - return FALSE; - - miImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); return TRUE; +bail_ctx: + glDisable(GL_COLOR_LOGIC_OP); + glamor_put_context(glamor_priv); +bail: + return FALSE; } void -glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, unsigned int nglyph, - CharInfoPtr *ppci, void *pglyphBase) +glamor_poly_glyph_blt(DrawablePtr drawable, GCPtr gc, + int start_x, int y, unsigned int nglyph, + CharInfoPtr *ppci, void *pglyph_base) { - _glamor_image_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase, - TRUE); + if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci, pglyph_base)) + return; + miPolyGlyphBlt(drawable, gc, start_x, y, nglyph, + ppci, pglyph_base); } Bool -glamor_image_glyph_blt_nf(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, unsigned int nglyph, - CharInfoPtr *ppci, void *pglyphBase) -{ - return _glamor_image_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, - pglyphBase, FALSE); -} - -static Bool -_glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, unsigned int nglyph, - CharInfoPtr *ppci, void *pglyphBase, Bool fallback) +glamor_poly_glyph_blt_nf(DrawablePtr drawable, GCPtr gc, + int start_x, int y, unsigned int nglyph, + CharInfoPtr *ppci, void *pglyph_base) { - if (glamor_poly_glyph_blt_pixels(pDrawable, pGC, x, y, nglyph, ppci)) + if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci, pglyph_base)) return TRUE; - - if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable) - && glamor_ddx_fallback_check_gc(pGC)) + if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) return FALSE; - - miPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + miPolyGlyphBlt(drawable, gc, start_x, y, nglyph, + ppci, pglyph_base); return TRUE; } -void -glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, unsigned int nglyph, - CharInfoPtr *ppci, void *pglyphBase) -{ - _glamor_poly_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase, - TRUE); -} - Bool -glamor_poly_glyph_blt_nf(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, unsigned int nglyph, - CharInfoPtr *ppci, void *pglyphBase) +glamor_image_glyph_blt_nf(DrawablePtr drawable, GCPtr gc, + int start_x, int y, unsigned int nglyph, + CharInfoPtr *ppci, void *pglyph_base) { - return _glamor_poly_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, - pglyphBase, FALSE); + miImageGlyphBlt(drawable, gc, start_x, y, nglyph, ppci, pglyph_base); + return TRUE; } static Bool diff --git a/xorg-server/glamor/glamor_pixmap.c b/xorg-server/glamor/glamor_pixmap.c index 891ecdd37..a811f6015 100644 --- a/xorg-server/glamor/glamor_pixmap.c +++ b/xorg-server/glamor/glamor_pixmap.c @@ -283,8 +283,6 @@ glamor_get_tex_format_type_from_pictformat_gl(PictFormatShort format, break; default: - LogMessageVerb(X_INFO, 0, - "fail to get matched format for %x \n", format); return -1; } return 0; @@ -980,7 +978,7 @@ glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, &no_alpha, &revert, &swap_rb, 1)) { glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth); - return TRUE; + return FALSE; } if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb)) return FALSE; diff --git a/xorg-server/glamor/glamor_points.c b/xorg-server/glamor/glamor_points.c index 5399f96e8..0d58e555f 100644 --- a/xorg-server/glamor/glamor_points.c +++ b/xorg-server/glamor/glamor_points.c @@ -35,8 +35,8 @@ static const glamor_facet glamor_facet_point = { .vs_exec = GLAMOR_POS(gl_Position, primitive), }; -Bool -glamor_poly_point_nf(DrawablePtr drawable, GCPtr gc, int mode, int npt, DDXPointPtr ppt) +static Bool +glamor_poly_point_gl(DrawablePtr drawable, GCPtr gc, int mode, int npt, DDXPointPtr ppt) { ScreenPtr screen = drawable->pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); @@ -123,7 +123,22 @@ void glamor_poly_point(DrawablePtr drawable, GCPtr gc, int mode, int npt, DDXPointPtr ppt) { - if (glamor_poly_point_nf(drawable, gc, mode, npt, ppt)) + if (glamor_poly_point_gl(drawable, gc, mode, npt, ppt)) return; miPolyPoint(drawable, gc, mode, npt, ppt); } + +Bool +glamor_poly_point_nf(DrawablePtr drawable, GCPtr gc, int mode, int npt, + DDXPointPtr ppt) +{ + if (glamor_poly_point_gl(drawable, gc, mode, npt, ppt)) + return TRUE; + + if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) + return FALSE; + + miPolyPoint(drawable, gc, mode, npt, ppt); + return TRUE; +} + diff --git a/xorg-server/glamor/glamor_polyfillrect.c b/xorg-server/glamor/glamor_polyfillrect.c deleted file mode 100644 index 1e361a44f..000000000 --- a/xorg-server/glamor/glamor_polyfillrect.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright © 2009 Intel Corporation - * Copyright © 1998 Keith Packard - * - * 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 (including the next - * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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: - * Eric Anholt <eric@anholt.net> - * - */ - -#include "glamor_priv.h" - -/** @file glamor_fillspans.c - * - * GC PolyFillRect implementation, taken straight from fb_fill.c - */ - -static Bool -_glamor_poly_fill_rect(DrawablePtr drawable, - GCPtr gc, int nrect, xRectangle *prect, Bool fallback) -{ - int fullX1, fullX2, fullY1, fullY2; - int xorg, yorg; - int n; - register BoxPtr pbox; - RegionPtr pClip = fbGetCompositeClip(gc); - Bool ret = FALSE; - - xorg = drawable->x; - yorg = drawable->y; - - while (nrect--) { - fullX1 = prect->x + xorg; - fullY1 = prect->y + yorg; - fullX2 = fullX1 + (int) prect->width; - fullY2 = fullY1 + (int) prect->height; - - n = REGION_NUM_RECTS(pClip); - pbox = REGION_RECTS(pClip); - /* - * clip the rectangle to each box in the clip region - * this is logically equivalent to calling Intersect(), - * but rectangles may overlap each other here. - */ - while (n--) { - int x1 = fullX1; - int x2 = fullX2; - int y1 = fullY1; - int y2 = fullY2; - - if (pbox->x1 > x1) - x1 = pbox->x1; - if (pbox->x2 < x2) - x2 = pbox->x2; - if (pbox->y1 > y1) - y1 = pbox->y1; - if (pbox->y2 < y2) - y2 = pbox->y2; - - pbox++; - if (x1 >= x2 || y1 >= y2) - continue; - if (!glamor_fill(drawable, gc, x1, y1, x2 - x1, y2 - y1, fallback)) { - nrect++; - goto fail; - } - } - prect++; - } - ret = TRUE; - goto done; - - fail: - - if (!fallback && glamor_ddx_fallback_check_pixmap(drawable) - && glamor_ddx_fallback_check_gc(gc)) - goto done; - - glamor_fallback(" to %p (%c)\n", - drawable, glamor_get_drawable_location(drawable)); - if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && - glamor_prepare_access_gc(gc)) { - fbPolyFillRect(drawable, gc, nrect, prect); - } - glamor_finish_access_gc(gc); - glamor_finish_access(drawable); - ret = TRUE; - - done: - return ret; -} - -void -glamor_poly_fill_rect(DrawablePtr drawable, - GCPtr gc, int nrect, xRectangle *prect) -{ - _glamor_poly_fill_rect(drawable, gc, nrect, prect, TRUE); -} - -Bool -glamor_poly_fill_rect_nf(DrawablePtr drawable, - GCPtr gc, int nrect, xRectangle *prect) -{ - return _glamor_poly_fill_rect(drawable, gc, nrect, prect, FALSE); -} diff --git a/xorg-server/glamor/glamor_priv.h b/xorg-server/glamor/glamor_priv.h index 4c305abfc..0cafac4b5 100644 --- a/xorg-server/glamor/glamor_priv.h +++ b/xorg-server/glamor/glamor_priv.h @@ -205,6 +205,7 @@ typedef struct glamor_screen_private { Bool yInverted; unsigned int tick; enum glamor_gl_flavor gl_flavor; + int glsl_version; int has_pack_invert; int has_fbo_blit; int has_map_buffer_range; @@ -223,6 +224,20 @@ typedef struct glamor_screen_private { /* glamor point shader */ glamor_program point_prog; + /* glamor spans shaders */ + glamor_program_fill fill_spans_program; + + /* glamor rect shaders */ + glamor_program_fill poly_fill_rect_program; + + /* glamor glyphblt shaders */ + glamor_program_fill poly_glyph_blt_progs; + + /* glamor text shaders */ + glamor_program_fill poly_text_progs; + glamor_program te_text_prog; + glamor_program image_text_prog; + /* vertext/elment_index buffer object for render */ GLuint vbo, ebo; /** Next offset within the VBO that glamor_get_vbo_space() will use. */ @@ -584,8 +599,6 @@ extern int glamor_debug_level; /* glamor.c */ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); -Bool glamor_destroy_pixmap(PixmapPtr pixmap); - glamor_pixmap_fbo *glamor_pixmap_detach_fbo(glamor_pixmap_private * pixmap_priv); void glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo); @@ -674,19 +687,9 @@ Bool glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, Bool glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, unsigned long fg_pixel); -/* glamor_fillspans.c */ -void glamor_fill_spans(DrawablePtr drawable, - GCPtr gc, - int n, DDXPointPtr points, int *widths, int sorted); - void glamor_init_solid_shader(ScreenPtr screen); void glamor_fini_solid_shader(ScreenPtr screen); -/* glamor_getspans.c */ -void glamor_get_spans(DrawablePtr drawable, - int wmax, DDXPointPtr points, int *widths, - int nspans, char *dst_start); - /* glamor_glyphs.c */ Bool glamor_realize_glyph_caches(ScreenPtr screen); void glamor_glyphs_fini(ScreenPtr screen); @@ -697,14 +700,6 @@ void glamor_glyphs(CARD8 op, INT16 xSrc, INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs); -/* glamor_setspans.c */ -void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, - DDXPointPtr points, int *widths, int n, int sorted); - -/* glamor_polyfillrect.c */ -void glamor_poly_fill_rect(DrawablePtr drawable, - GCPtr gc, int nrect, xRectangle *prect); - /* glamor_polylines.c */ void glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, DDXPointPtr points); @@ -967,6 +962,39 @@ RegionPtr glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int dstx, int dsty, unsigned long bitPlane); +/* glamor_text.c */ +int glamor_poly_text8(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, char *chars); + +int glamor_poly_text16(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, unsigned short *chars); + +void glamor_image_text8(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, char *chars); + +void glamor_image_text16(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, unsigned short *chars); + +/* glamor_spans.c */ +void +glamor_fill_spans(DrawablePtr drawable, + GCPtr gc, + int n, DDXPointPtr points, int *widths, int sorted); + +void +glamor_get_spans(DrawablePtr drawable, int wmax, + DDXPointPtr points, int *widths, int count, char *dst); + +void +glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int numPoints, int sorted); + +/* glamor_rects.c */ +void +glamor_poly_fill_rect(DrawablePtr drawable, + GCPtr gc, int nrect, xRectangle *prect); + +/* glamor_glyphblt.c */ void glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, void *pglyphBase); @@ -992,9 +1020,6 @@ void glamor_composite_rectangles(CARD8 op, xRenderColor *color, int num_rects, xRectangle *rects); -extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen, - struct glamor_context *glamor_ctx); - /* glamor_xv */ typedef struct { uint32_t transform_index; @@ -1039,4 +1064,6 @@ void glamor_fini_xv_shader(ScreenPtr screen); //#define GLYPHS_NO_EDEGEMAP_OVERLAP_CHECK #define GLYPHS_EDEGE_OVERLAP_LOOSE_CHECK +#include "glamor_font.h" + #endif /* GLAMOR_PRIV_H */ diff --git a/xorg-server/glamor/glamor_program.c b/xorg-server/glamor/glamor_program.c index e2e1434ee..0f4d0f06a 100644 --- a/xorg-server/glamor/glamor_program.c +++ b/xorg-server/glamor/glamor_program.c @@ -45,9 +45,8 @@ use_tile(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg) static const glamor_facet glamor_fill_tile = { .name = "tile", - .version = 130, - .vs_exec = " fill_pos = fill_offset + primitive.xy + pos;\n", - .fs_exec = " gl_FragColor = texelFetch(sampler, ivec2(mod(fill_pos,fill_size)), 0);\n", + .vs_exec = " fill_pos = (fill_offset + primitive.xy + pos) / fill_size;\n", + .fs_exec = " gl_FragColor = texture2D(sampler, fill_pos);\n", .locations = glamor_program_location_fill, .use = use_tile, }; @@ -108,6 +107,7 @@ static glamor_location_var location_vars[] = { { .location = glamor_program_location_fill, .vs_vars = ("uniform vec2 fill_offset;\n" + "uniform vec2 fill_size;\n" "varying vec2 fill_pos;\n"), .fs_vars = ("uniform sampler2D sampler;\n" "uniform vec2 fill_size;\n" @@ -240,16 +240,8 @@ glamor_build_program(ScreenPtr screen, flags |= fill->flags; version = MAX(version, fill->version); - if (version >= 130) { - - /* Would be nice to have a cleaner test for GLSL 1.30 support, - * but for now this should suffice - */ - if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP || - epoxy_gl_version() < 30) { - goto fail; - } - } + if (version > glamor_priv->glsl_version) + goto fail; vs_vars = vs_location_vars(locations); fs_vars = fs_location_vars(locations); diff --git a/xorg-server/glamor/glamor_rects.c b/xorg-server/glamor/glamor_rects.c new file mode 100644 index 000000000..7731edec4 --- /dev/null +++ b/xorg-server/glamor/glamor_rects.c @@ -0,0 +1,189 @@ +/* + * Copyright © 2014 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "glamor_priv.h" +#include "glamor_program.h" +#include "glamor_transform.h" + +static const glamor_facet glamor_facet_polyfillrect_130 = { + .name = "poly_fill_rect", + .version = 130, + .vs_vars = "attribute vec4 primitive;\n", + .vs_exec = (" vec2 pos = primitive.zw * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n" + GLAMOR_POS(gl_Position, (primitive.xy + pos))), +}; + +static const glamor_facet glamor_facet_polyfillrect_120 = { + .name = "poly_fill_rect", + .vs_vars = "attribute vec2 primitive;\n", + .vs_exec = (" vec2 pos = vec2(0,0);\n" + GLAMOR_POS(gl_Position, primitive.xy)), +}; + +static Bool +glamor_poly_fill_rect_gl(DrawablePtr drawable, + GCPtr gc, int nrect, xRectangle *prect) +{ + ScreenPtr screen = drawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv; + glamor_program *prog; + int off_x, off_y; + GLshort *v; + char *vbo_offset; + int box_x, box_y; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + goto bail; + + glamor_get_context(glamor_priv); + + if (glamor_priv->glsl_version >= 130) { + prog = glamor_use_program_fill(pixmap, gc, + &glamor_priv->poly_fill_rect_program, + &glamor_facet_polyfillrect_130); + + if (!prog) + goto bail_ctx; + + /* Set up the vertex buffers for the points */ + + v = glamor_get_vbo_space(drawable->pScreen, nrect * sizeof (xRectangle), &vbo_offset); + + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1); + glVertexAttribPointer(GLAMOR_VERTEX_POS, 4, GL_SHORT, GL_FALSE, + 4 * sizeof (short), vbo_offset); + + memcpy(v, prect, nrect * sizeof (xRectangle)); + + glamor_put_vbo_space(screen); + } else { + int n; + + prog = glamor_use_program_fill(pixmap, gc, + &glamor_priv->poly_fill_rect_program, + &glamor_facet_polyfillrect_120); + + if (!prog) + goto bail_ctx; + + /* Set up the vertex buffers for the points */ + + v = glamor_get_vbo_space(drawable->pScreen, nrect * 8 * sizeof (short), &vbo_offset); + + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, + 2 * sizeof (short), vbo_offset); + + for (n = 0; n < nrect; n++) { + v[0] = prect->x; v[1] = prect->y; + v[2] = prect->x; v[3] = prect->y + prect->height; + v[4] = prect->x + prect->width; v[5] = prect->y + prect->height; + v[6] = prect->x + prect->width; v[7] = prect->y; + prect++; + v += 8; + } + + glamor_put_vbo_space(screen); + } + + glEnable(GL_SCISSOR_TEST); + + glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + int nbox = RegionNumRects(gc->pCompositeClip); + BoxPtr box = RegionRects(gc->pCompositeClip); + + glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, FALSE, prog->matrix_uniform, &off_x, &off_y); + + while (nbox--) { + glScissor(box->x1 + off_x, + box->y1 + off_y, + box->x2 - box->x1, + box->y2 - box->y1); + box++; + if (glamor_priv->glsl_version >= 130) + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nrect); + else { + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + glDrawArrays(GL_QUADS, 0, nrect * 4); + } else { + int i; + for (i = 0; i < nrect; i++) { + glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4); + } + } + } + } + } + + glDisable(GL_SCISSOR_TEST); + glDisable(GL_COLOR_LOGIC_OP); + if (glamor_priv->glsl_version >= 130) + glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0); + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + + glamor_put_context(glamor_priv); + return TRUE; +bail_ctx: + glDisable(GL_COLOR_LOGIC_OP); + glamor_put_context(glamor_priv); +bail: + return FALSE; +} + +static void +glamor_poly_fill_rect_bail(DrawablePtr drawable, + GCPtr gc, int nrect, xRectangle *prect) +{ + glamor_fallback("to %p (%c)\n", drawable, + glamor_get_drawable_location(drawable)); + if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && + glamor_prepare_access_gc(gc)) { + fbPolyFillRect(drawable, gc, nrect, prect); + } + glamor_finish_access_gc(gc); + glamor_finish_access(drawable); +} + +void +glamor_poly_fill_rect(DrawablePtr drawable, + GCPtr gc, int nrect, xRectangle *prect) +{ + if (glamor_poly_fill_rect_gl(drawable, gc, nrect, prect)) + return; + glamor_poly_fill_rect_bail(drawable, gc, nrect, prect); +} + +Bool +glamor_poly_fill_rect_nf(DrawablePtr drawable, + GCPtr gc, int nrect, xRectangle *prect) +{ + if (glamor_poly_fill_rect_gl(drawable, gc, nrect, prect)) + return TRUE; + if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) + return FALSE; + glamor_poly_fill_rect_bail(drawable, gc, nrect, prect); + return TRUE; +} diff --git a/xorg-server/glamor/glamor_setspans.c b/xorg-server/glamor/glamor_setspans.c deleted file mode 100644 index a51e4c5be..000000000 --- a/xorg-server/glamor/glamor_setspans.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright © 2009 Intel Corporation - * - * 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 (including the next - * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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: - * Eric Anholt <eric@anholt.net> - * Zhigang Gong <zhigang.gong@linux.intel.com> - * - */ - -#include "glamor_priv.h" - -static Bool -_glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, - DDXPointPtr points, int *widths, int numPoints, int sorted, - Bool fallback) -{ - PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); - glamor_pixmap_private *dest_pixmap_priv; - int i; - uint8_t *drawpixels_src = (uint8_t *) src; - RegionPtr clip = fbGetCompositeClip(gc); - BoxRec *pbox; - int x_off, y_off; - Bool ret = FALSE; - - dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { - glamor_fallback("pixmap has no fbo.\n"); - goto fail; - } - - if (gc->alu != GXcopy) { - glamor_fallback("SetSpans with non-copy ALU.\n"); - goto fail; - } - - if (!glamor_set_planemask(dest_pixmap, gc->planemask)) - goto fail; - - glamor_get_drawable_deltas(drawable, dest_pixmap, &x_off, &y_off); - for (i = 0; i < numPoints; i++) { - - int n = REGION_NUM_RECTS(clip); - - pbox = REGION_RECTS(clip); - while (n--) { - int x1 = points[i].x; - int x2 = x1 + widths[i]; - int y1 = points[i].y; - - if (pbox->y1 > points[i].y || pbox->y2 < points[i].y) - break; - x1 = x1 > pbox->x1 ? x1 : pbox->x1; - x2 = x2 < pbox->x2 ? x2 : pbox->x2; - if (x1 >= x2) - continue; - glamor_upload_sub_pixmap_to_texture(dest_pixmap, x1 + x_off, - y1 + y_off, x2 - x1, 1, - PixmapBytePad(widths[i], - drawable->depth), - drawpixels_src, 0); - } - drawpixels_src += PixmapBytePad(widths[i], drawable->depth); - } - ret = TRUE; - goto done; - - fail: - if (!fallback && glamor_ddx_fallback_check_pixmap(drawable)) - goto done; - - glamor_fallback("to %p (%c)\n", - drawable, glamor_get_drawable_location(drawable)); - if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && - glamor_prepare_access_gc(gc)) { - fbSetSpans(drawable, gc, src, points, widths, numPoints, sorted); - } - glamor_finish_access_gc(gc); - glamor_finish_access(drawable); - ret = TRUE; - - done: - return ret; -} - -void -glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, - DDXPointPtr points, int *widths, int n, int sorted) -{ - _glamor_set_spans(drawable, gc, src, points, widths, n, sorted, TRUE); -} - -Bool -glamor_set_spans_nf(DrawablePtr drawable, GCPtr gc, char *src, - DDXPointPtr points, int *widths, int n, int sorted) -{ - return _glamor_set_spans(drawable, gc, src, points, - widths, n, sorted, FALSE); -} diff --git a/xorg-server/glamor/glamor_spans.c b/xorg-server/glamor/glamor_spans.c new file mode 100644 index 000000000..98842cdde --- /dev/null +++ b/xorg-server/glamor/glamor_spans.c @@ -0,0 +1,438 @@ +/* + * Copyright © 2014 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "glamor_priv.h" +#include "glamor_transform.h" +#include "glamor_transfer.h" + +glamor_program fill_spans_progs[4]; + +static const glamor_facet glamor_facet_fillspans_130 = { + .name = "fill_spans", + .version = 130, + .vs_vars = "attribute vec3 primitive;\n", + .vs_exec = (" vec2 pos = vec2(primitive.z,1) * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n" + GLAMOR_POS(gl_Position, (primitive.xy + pos))), +}; + +static const glamor_facet glamor_facet_fillspans_120 = { + .name = "fill_spans", + .vs_vars = "attribute vec2 primitive;\n", + .vs_exec = (" vec2 pos = vec2(0,0);\n" + GLAMOR_POS(gl_Position, primitive.xy)), +}; + +static Bool +glamor_fill_spans_gl(DrawablePtr drawable, + GCPtr gc, + int n, DDXPointPtr points, int *widths, int sorted) +{ + ScreenPtr screen = drawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv; + glamor_program *prog; + int off_x, off_y; + GLshort *v; + char *vbo_offset; + int c; + int box_x, box_y; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + goto bail; + + glamor_get_context(glamor_priv); + + if (glamor_priv->glsl_version >= 130) { + prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program, + &glamor_facet_fillspans_130); + + if (!prog) + goto bail_ctx; + + /* Set up the vertex buffers for the points */ + + v = glamor_get_vbo_space(drawable->pScreen, n * (4 * sizeof (GLshort)), &vbo_offset); + + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1); + glVertexAttribPointer(GLAMOR_VERTEX_POS, 3, GL_SHORT, GL_FALSE, + 4 * sizeof (GLshort), vbo_offset); + + for (c = 0; c < n; c++) { + v[0] = points->x; + v[1] = points->y; + v[2] = *widths++; + points++; + v += 4; + } + + glamor_put_vbo_space(screen); + } else { + prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program, + &glamor_facet_fillspans_120); + + if (!prog) + goto bail_ctx; + + /* Set up the vertex buffers for the points */ + + v = glamor_get_vbo_space(drawable->pScreen, n * 8 * sizeof (short), &vbo_offset); + + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, + 2 * sizeof (short), vbo_offset); + + for (c = 0; c < n; c++) { + v[0] = points->x; v[1] = points->y; + v[2] = points->x; v[3] = points->y + 1; + v[4] = points->x + *widths; v[5] = points->y + 1; + v[6] = points->x + *widths; v[7] = points->y; + + widths++; + points++; + v += 8; + } + + glamor_put_vbo_space(screen); + } + + glEnable(GL_SCISSOR_TEST); + + glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + int nbox = RegionNumRects(gc->pCompositeClip); + BoxPtr box = RegionRects(gc->pCompositeClip); + + glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, FALSE, prog->matrix_uniform, &off_x, &off_y); + + while (nbox--) { + glScissor(box->x1 + off_x, + box->y1 + off_y, + box->x2 - box->x1, + box->y2 - box->y1); + box++; + if (glamor_priv->glsl_version >= 130) + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, n); + else { + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + glDrawArrays(GL_QUADS, 0, 4 * n); + } else { + int i; + for (i = 0; i < n; i++) { + glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4); + } + } + } + } + } + + glDisable(GL_SCISSOR_TEST); + glDisable(GL_COLOR_LOGIC_OP); + if (glamor_priv->glsl_version >= 130) + glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0); + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + + glamor_put_context(glamor_priv); + return TRUE; +bail_ctx: + glDisable(GL_COLOR_LOGIC_OP); + glamor_put_context(glamor_priv); +bail: + return FALSE; +} + +static void +glamor_fill_spans_bail(DrawablePtr drawable, + GCPtr gc, + int n, DDXPointPtr points, int *widths, int sorted) +{ + if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && + glamor_prepare_access_gc(gc)) { + fbFillSpans(drawable, gc, n, points, widths, sorted); + } + glamor_finish_access_gc(gc); + glamor_finish_access(drawable); +} + +void +glamor_fill_spans(DrawablePtr drawable, + GCPtr gc, + int n, DDXPointPtr points, int *widths, int sorted) +{ + if (glamor_fill_spans_gl(drawable, gc, n, points, widths, sorted)) + return; + glamor_fill_spans_bail(drawable, gc, n, points, widths, sorted); +} + +Bool +glamor_fill_spans_nf(DrawablePtr drawable, + GCPtr gc, + int n, DDXPointPtr points, int *widths, int sorted) +{ + if (glamor_fill_spans_gl(drawable, gc, n, points, widths, sorted)) + return TRUE; + + if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) + return FALSE; + + glamor_fill_spans_bail(drawable, gc, n, points, widths, sorted); + return TRUE; +} + +static Bool +glamor_get_spans_gl(DrawablePtr drawable, int wmax, + DDXPointPtr points, int *widths, int count, char *dst) +{ + ScreenPtr screen = drawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv; + int box_x, box_y; + int n; + char *d; + GLenum type; + GLenum format; + int off_x, off_y; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + goto bail; + + glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); + + glamor_format_for_pixmap(pixmap, &format, &type); + + glamor_get_context(glamor_priv); + + glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_x, box_y); + glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(pixmap_priv, box_x, box_y); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->fb); + glPixelStorei(GL_PACK_ALIGNMENT, 4); + + d = dst; + for (n = 0; n < count; n++) { + int x1 = points[n].x + off_x; + int y = points[n].y + off_y; + int w = widths[n]; + int x2 = x1 + w; + char *l; + + l = d; + d += PixmapBytePad(w, drawable->depth); + + /* clip */ + if (x1 < box->x1) { + l += (box->x1 - x1) * (drawable->bitsPerPixel >> 3); + x1 = box->x1; + } + if (x2 > box->x2) + x2 = box->x2; + + if (x1 >= x2) + continue; + if (y < box->y1) + continue; + if (y >= box->y2) + continue; + + glReadPixels(x1 - box->x1, y - box->y1, x2 - x1, 1, format, type, l); + } + } + + glamor_put_context(glamor_priv); + return TRUE; +bail: + return FALSE; +} + +static void +glamor_get_spans_bail(DrawablePtr drawable, int wmax, + DDXPointPtr points, int *widths, int count, char *dst) +{ + if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO)) + fbGetSpans(drawable, wmax, points, widths, count, dst); + glamor_finish_access(drawable); +} + +void +glamor_get_spans(DrawablePtr drawable, int wmax, + DDXPointPtr points, int *widths, int count, char *dst) +{ + if (glamor_get_spans_gl(drawable, wmax, points, widths, count, dst)) + return; + glamor_get_spans_bail(drawable, wmax, points, widths, count, dst); +} + +Bool +glamor_get_spans_nf(DrawablePtr drawable, int wmax, + DDXPointPtr points, int *widths, int count, char *dst) +{ + if (glamor_get_spans_gl(drawable, wmax, points, widths, count, dst)) + return TRUE; + + if (glamor_ddx_fallback_check_pixmap(drawable)) + return FALSE; + + glamor_get_spans_bail(drawable, wmax, points, widths, count, dst); + return TRUE; +} + +static Bool +glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int numPoints, int sorted) +{ + ScreenPtr screen = drawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv; + int box_x, box_y; + int n; + char *s; + GLenum type; + GLenum format; + int off_x, off_y; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + goto bail; + + if (gc->alu != GXcopy) + goto bail; + + if (!glamor_pm_is_solid(&pixmap->drawable, gc->planemask)) + goto bail; + + glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); + glamor_format_for_pixmap(pixmap, &format, &type); + + glamor_get_context(glamor_priv); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + + glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_x, box_y); + glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(pixmap_priv, box_x, box_y); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, fbo->tex); + + s = src; + for (n = 0; n < numPoints; n++) { + + BoxPtr clip_box = RegionRects(gc->pCompositeClip); + int nclip_box = RegionNumRects(gc->pCompositeClip); + int w = widths[n]; + int y = points[n].y; + int x = points[n].x; + + while (nclip_box--) { + int x1 = x; + int x2 = x + w; + int y1 = y; + char *l = s; + + /* clip to composite clip */ + if (x1 < clip_box->x1) { + l += (clip_box->x1 - x1) * (drawable->bitsPerPixel >> 3); + x1 = clip_box->x1; + } + if (x2 > clip_box->x2) + x2 = clip_box->x2; + + if (y < clip_box->y1) + continue; + if (y >= clip_box->y2) + continue; + + /* adjust to pixmap coordinates */ + x1 += off_x; + x2 += off_x; + y1 += off_y; + + if (x1 < box->x1) { + l += (box->x1 - x1) * (drawable->bitsPerPixel >> 3); + x1 = box->x1; + } + if (x2 > box->x2) + x2 = box->x2; + + if (x1 >= x2) + continue; + if (y1 < box->y1) + continue; + if (y1 >= box->y2) + continue; + + glTexSubImage2D(GL_TEXTURE_2D, 0, + x1 - box->x1, y1 - box->y1, x2 - x1, 1, + format, type, + l); + } + s += PixmapBytePad(w, drawable->depth); + } + } + + glamor_put_context(glamor_priv); + return TRUE; + +bail: + return FALSE; +} + +static void +glamor_set_spans_bail(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int numPoints, int sorted) +{ + if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && glamor_prepare_access_gc(gc)) + fbSetSpans(drawable, gc, src, points, widths, numPoints, sorted); + glamor_finish_access_gc(gc); + glamor_finish_access(drawable); +} + +void +glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int numPoints, int sorted) +{ + if (glamor_set_spans_gl(drawable, gc, src, points, widths, numPoints, sorted)) + return; + glamor_set_spans_bail(drawable, gc, src, points, widths, numPoints, sorted); +} + +Bool +glamor_set_spans_nf(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int numPoints, int sorted) +{ + if (glamor_set_spans_gl(drawable, gc, src, points, widths, numPoints, sorted)) + return TRUE; + + if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) + return FALSE; + + glamor_set_spans_bail(drawable, gc, src, points, widths, numPoints, sorted); + return TRUE; +} diff --git a/xorg-server/glamor/glamor_text.c b/xorg-server/glamor/glamor_text.c new file mode 100644 index 000000000..0e4b74c56 --- /dev/null +++ b/xorg-server/glamor/glamor_text.c @@ -0,0 +1,526 @@ +/* + * Copyright © 2014 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "glamor_priv.h" +#include <dixfontstr.h> +#include "glamor_transform.h" + +/* + * Fill in the array of charinfo pointers for the provided characters. For + * missing characters, place a NULL in the array so that the charinfo array + * aligns exactly with chars + */ + +static void +glamor_get_glyphs(FontPtr font, glamor_font_t *glamor_font, + int count, char *chars, Bool sixteen, CharInfoPtr *charinfo) +{ + unsigned long nglyphs; + FontEncoding encoding; + int char_step; + + if (sixteen) { + char_step = 2; + if (FONTLASTROW(font) == 0) + encoding = Linear16Bit; + else + encoding = TwoD16Bit; + } else { + char_step = 1; + encoding = Linear8Bit; + } + + /* If the font has a default character, then we don't have to + * worry about missing glyphs, so just get the whole string all at + * once. Otherwise, we have to fetch chars one at a time to notice + * missing ones. + */ + if (glamor_font->default_char) { + GetGlyphs(font, (unsigned long) count, (unsigned char *) chars, + encoding, &nglyphs, charinfo); + } else { + int c; + for (c = 0; c < count; c++) { + GetGlyphs(font, 1, (unsigned char *) chars, + encoding, &nglyphs, &charinfo[c]); + if (!nglyphs) + charinfo[c] = NULL; + chars += char_step; + } + } +} + +/* + * Construct quads for the provided list of characters and draw them + */ + +static int +glamor_text(DrawablePtr drawable, GCPtr gc, + glamor_font_t *glamor_font, + glamor_program *prog, + int x, int y, + int count, char *s_chars, CharInfoPtr *charinfo, + Bool sixteen) +{ + unsigned char *chars = (unsigned char *) s_chars; + FontPtr font = gc->font; + int off_x, off_y; + int c; + int nglyph; + GLshort *v; + char *vbo_offset; + CharInfoPtr ci; + int firstRow = font->info.firstRow; + int firstCol = font->info.firstCol; + int glyph_spacing_x = glamor_font->glyph_width_bytes * 8; + int glyph_spacing_y = glamor_font->glyph_height; + int box_x, box_y; + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + + /* Set the font as texture 1 */ + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, glamor_font->texture_id); + glUniform1i(prog->font_uniform, 1); + + /* Set up the vertex buffers for the font and destination */ + + v = glamor_get_vbo_space(drawable->pScreen, count * (6 * sizeof (GLshort)), &vbo_offset); + + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1); + glVertexAttribPointer(GLAMOR_VERTEX_POS, 4, GL_SHORT, GL_FALSE, + 6 * sizeof (GLshort), vbo_offset); + + glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 1); + glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_SHORT, GL_FALSE, + 6 * sizeof (GLshort), vbo_offset + 4 * sizeof (GLshort)); + + /* Set the vertex coordinates */ + nglyph = 0; + + for (c = 0; c < count; c++) { + if ((ci = *charinfo++)) { + int x1 = x + ci->metrics.leftSideBearing; + int y1 = y - ci->metrics.ascent; + int width = GLYPHWIDTHPIXELS(ci); + int height = GLYPHHEIGHTPIXELS(ci); + int tx, ty = 0; + int row = 0, col; + + x += ci->metrics.characterWidth; + + if (sixteen) { + if (ci == glamor_font->default_char) { + row = glamor_font->default_row; + col = glamor_font->default_col; + } else { + row = chars[0]; + col = chars[1]; + } + if (FONTLASTROW(font) != 0) + ty = (row - firstRow) * glyph_spacing_y; + else + col += row << 8; + } else { + if (ci == glamor_font->default_char) + col = glamor_font->default_col; + else + col = chars[0]; + } + + tx = (col - firstCol) * glyph_spacing_x; + + v[ 0] = x1; + v[ 1] = y1; + v[ 2] = width; + v[ 3] = height; + v[ 4] = tx; + v[ 5] = ty; + + v += 6; + nglyph++; + } + chars += 1 + sixteen; + } + glamor_put_vbo_space(drawable->pScreen); + + if (nglyph != 0) { + + glEnable(GL_SCISSOR_TEST); + + glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + BoxPtr box = RegionRects(gc->pCompositeClip); + int nbox = RegionNumRects(gc->pCompositeClip); + + glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, FALSE, prog->matrix_uniform, &off_x, &off_y); + + /* Run over the clip list, drawing the glyphs + * in each box + */ + + while (nbox--) { + glScissor(box->x1 + off_x, + box->y1 + off_y, + box->x2 - box->x1, + box->y2 - box->y1); + box++; + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nglyph); + } + } + glDisable(GL_SCISSOR_TEST); + } + + glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 0); + glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0); + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + glDisable(GL_COLOR_LOGIC_OP); + + return x; +} + +static const char vs_vars_text[] = + "attribute vec4 primitive;\n" + "attribute vec2 source;\n" + "varying vec2 glyph_pos;\n"; + +static const char vs_exec_text[] = + " vec2 pos = primitive.zw * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n" + GLAMOR_POS(gl_Position, (primitive.xy + pos)) + " glyph_pos = source + pos;\n"; + +static const char fs_vars_text[] = + "varying vec2 glyph_pos;\n"; + +static const char fs_exec_text[] = + " ivec2 itile_texture = ivec2(glyph_pos);\n" + " uint x = uint(itile_texture.x & 7);\n" + " itile_texture.x >>= 3;\n" + " uint texel = texelFetch(font, itile_texture, 0).x;\n" + " uint bit = (texel >> x) & uint(1);\n" + " if (bit == uint(0))\n" + " discard;\n"; + +static const char fs_exec_te[] = + " ivec2 itile_texture = ivec2(glyph_pos);\n" + " uint x = uint(itile_texture.x & 7);\n" + " itile_texture.x >>= 3;\n" + " uint texel = texelFetch(font, itile_texture, 0).x;\n" + " uint bit = (texel >> x) & uint(1);\n" + " if (bit == uint(0))\n" + " gl_FragColor = bg;\n" + " else\n" + " gl_FragColor = fg;\n"; + +static const glamor_facet glamor_facet_poly_text = { + .name = "poly_text", + .version = 130, + .vs_vars = vs_vars_text, + .vs_exec = vs_exec_text, + .fs_vars = fs_vars_text, + .fs_exec = fs_exec_text, + .source_name = "source", + .locations = glamor_program_location_font, +}; + +static Bool +glamor_poly_text(DrawablePtr drawable, GCPtr gc, + int x, int y, int count, char *chars, Bool sixteen, int *final_pos) +{ + ScreenPtr screen = drawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_program *prog; + glamor_pixmap_private *pixmap_priv; + glamor_font_t *glamor_font; + CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */ + + glamor_font = glamor_font_get(drawable->pScreen, gc->font); + if (!glamor_font) + goto bail; + + glamor_get_glyphs(gc->font, glamor_font, count, chars, sixteen, charinfo); + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + goto bail; + + glamor_get_context(glamor_priv); + + prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_text_progs, &glamor_facet_poly_text); + + if (!prog) + goto bail_ctx; + + x = glamor_text(drawable, gc, glamor_font, prog, + x, y, count, chars, charinfo, sixteen); + + glDisable(GL_COLOR_LOGIC_OP); + + glamor_put_context(glamor_priv); + + glamor_priv->state = RENDER_STATE; + glamor_priv->render_idle_cnt = 0; + + *final_pos = x; + return TRUE; + +bail_ctx: + glDisable(GL_COLOR_LOGIC_OP); + glamor_put_context(glamor_priv); +bail: + return FALSE; +} + +Bool +glamor_poly_text8_nf(DrawablePtr drawable, GCPtr gc, + int x, int y, int count, char *chars, int *final_pos) +{ + if (glamor_poly_text(drawable, gc, x, y, count, chars, FALSE, final_pos)) + return TRUE; + if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) + return FALSE; + *final_pos = miPolyText8(drawable, gc, x, y, count, chars); + return TRUE; +} + +int +glamor_poly_text8(DrawablePtr drawable, GCPtr gc, + int x, int y, int count, char *chars) +{ + int final_pos; + + if (glamor_poly_text(drawable, gc, x, y, count, chars, FALSE, &final_pos)) + return final_pos; + return miPolyText8(drawable, gc, x, y, count, chars); +} + +Bool +glamor_poly_text16_nf(DrawablePtr drawable, GCPtr gc, + int x, int y, int count, unsigned short *chars, int *final_pos) +{ + if (glamor_poly_text(drawable, gc, x, y, count, (char *) chars, TRUE, final_pos)) + return TRUE; + + if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) + return FALSE; + *final_pos = miPolyText16(drawable, gc, x, y, count, chars); + return TRUE; +} + +int +glamor_poly_text16(DrawablePtr drawable, GCPtr gc, + int x, int y, int count, unsigned short *chars) +{ + int final_pos; + + if (glamor_poly_text(drawable, gc, x, y, count, (char *) chars, TRUE, &final_pos)) + return final_pos; + return miPolyText16(drawable, gc, x, y, count, chars); +} + +/* + * Draw image text, which is always solid in copy mode and has the + * background cleared while painting the text. For fonts which have + * their bitmap metrics exactly equal to the area to clear, we can use + * the accelerated version which paints both fg and bg at the same + * time. Otherwise, clear the whole area and then paint the glyphs on + * top + */ + +static const glamor_facet glamor_facet_image_text = { + .name = "image_text", + .version = 130, + .vs_vars = vs_vars_text, + .vs_exec = vs_exec_text, + .fs_vars = fs_vars_text, + .fs_exec = fs_exec_text, + .source_name = "source", + .locations = glamor_program_location_font, +}; + +static Bool +use_image_solid(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg) +{ + return glamor_set_solid(pixmap, gc, FALSE, prog->fg_uniform); +} + +static const glamor_facet glamor_facet_image_fill = { + .name = "solid", + .fs_exec = " gl_FragColor = fg;\n", + .locations = glamor_program_location_fg, + .use = use_image_solid, +}; + +static Bool +glamor_te_text_use(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg) +{ + if (!glamor_set_solid(pixmap, gc, FALSE, prog->fg_uniform)) + return FALSE; + glamor_set_color(pixmap, gc->bgPixel, prog->bg_uniform); + return TRUE; +} + +static const glamor_facet glamor_facet_te_text = { + .name = "te_text", + .version = 130, + .vs_vars = vs_vars_text, + .vs_exec = vs_exec_text, + .fs_vars = fs_vars_text, + .fs_exec = fs_exec_te, + .locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_font, + .source_name = "source", + .use = glamor_te_text_use, +}; + +static Bool +glamor_image_text(DrawablePtr drawable, GCPtr gc, + int x, int y, int count, char *chars, + Bool sixteen) +{ + ScreenPtr screen = drawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_program *prog; + glamor_pixmap_private *pixmap_priv; + glamor_font_t *glamor_font; + const glamor_facet *prim_facet; + const glamor_facet *fill_facet; + CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */ + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return FALSE; + + glamor_font = glamor_font_get(drawable->pScreen, gc->font); + if (!glamor_font) + return FALSE; + + glamor_get_glyphs(gc->font, glamor_font, count, chars, sixteen, charinfo); + + glamor_get_context(glamor_priv); + + if (TERMINALFONT(gc->font)) + prog = &glamor_priv->te_text_prog; + else + prog = &glamor_priv->image_text_prog; + + if (prog->failed) + goto bail; + + if (!prog->prog) { + if (TERMINALFONT(gc->font)) { + prim_facet = &glamor_facet_te_text; + fill_facet = NULL; + } else { + prim_facet = &glamor_facet_image_text; + fill_facet = &glamor_facet_image_fill; + } + + if (!glamor_build_program(screen, prog, prim_facet, fill_facet)) + goto bail; + } + + if (!TERMINALFONT(gc->font)) { + int width = 0; + int c; + RegionRec region; + BoxRec box; + int off_x, off_y; + + /* Check planemask before drawing background to + * bail early if it's not OK + */ + if (!glamor_set_planemask(pixmap, gc->planemask)) + goto bail; + for (c = 0; c < count; c++) + if (charinfo[c]) + width += charinfo[c]->metrics.characterWidth; + + glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); + + if (width >= 0) { + box.x1 = off_x + drawable->x + x; + box.x2 = off_x + drawable->x + x + width; + } else { + box.x1 = off_x + drawable->x + x + width; + box.x2 = off_x + drawable->x + x; + } + box.y1 = off_y + drawable->y + y - gc->font->info.fontAscent; + box.y2 = off_y + drawable->y + y + gc->font->info.fontDescent; + RegionInit(®ion, &box, 1); + RegionIntersect(®ion, ®ion, gc->pCompositeClip); + glamor_solid_boxes(pixmap, RegionRects(®ion), RegionNumRects(®ion), gc->bgPixel); + RegionUninit(®ion); + } + + if (!glamor_use_program(pixmap, gc, prog, NULL)) + goto bail; + + (void) glamor_text(drawable, gc, glamor_font, prog, + x, y, count, chars, charinfo, sixteen); + + glamor_put_context(glamor_priv); + + glamor_priv->state = RENDER_STATE; + glamor_priv->render_idle_cnt = 0; + + return TRUE; + +bail: + glDisable(GL_COLOR_LOGIC_OP); + glamor_put_context(glamor_priv); + return FALSE; +} + +Bool +glamor_image_text8_nf(DrawablePtr drawable, GCPtr gc, + int x, int y, int count, char *chars) +{ + return glamor_image_text(drawable, gc, x, y, count, chars, FALSE); +} + +void +glamor_image_text8(DrawablePtr drawable, GCPtr gc, + int x, int y, int count, char *chars) +{ + if (!glamor_image_text(drawable, gc, x, y, count, chars, FALSE)) + miImageText8(drawable, gc, x, y, count, chars); +} + +Bool +glamor_image_text16_nf(DrawablePtr drawable, GCPtr gc, + int x, int y, int count, unsigned short *chars) +{ + return glamor_image_text(drawable, gc, x, y, count, (char *) chars, FALSE); +} + +void +glamor_image_text16(DrawablePtr drawable, GCPtr gc, + int x, int y, int count, unsigned short *chars) +{ + if (!glamor_image_text(drawable, gc, x, y, count, (char *) chars, TRUE)) + miImageText16(drawable, gc, x, y, count, chars); +} diff --git a/xorg-server/glamor/glamor_transfer.c b/xorg-server/glamor/glamor_transfer.c new file mode 100644 index 000000000..0378bb076 --- /dev/null +++ b/xorg-server/glamor/glamor_transfer.c @@ -0,0 +1,264 @@ +/* + * Copyright © 2014 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "glamor_priv.h" +#include "glamor_transfer.h" + +/* XXX a kludge for now */ +void +glamor_format_for_pixmap(PixmapPtr pixmap, GLenum *format, GLenum *type) +{ + switch (pixmap->drawable.depth) { + case 24: + case 32: + *format = GL_BGRA; + *type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + case 16: + *format = GL_RGB; + *type = GL_UNSIGNED_SHORT_5_6_5; + break; + case 15: + *format = GL_BGRA; + *type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + break; + case 8: + *format = GL_ALPHA; + *type = GL_UNSIGNED_BYTE; + break; + default: + FatalError("Invalid pixmap depth %d\n", pixmap->drawable.depth); + break; + } +} + +/* + * Write a region of bits into a pixmap + */ +void +glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox, + int dx_src, int dy_src, + int dx_dst, int dy_dst, + uint8_t *bits, uint32_t byte_stride) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap); + int box_x, box_y; + int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3; + GLenum type; + GLenum format; + + glamor_format_for_pixmap(pixmap, &format, &type); + + glamor_get_context(glamor_priv); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glPixelStorei(GL_UNPACK_ROW_LENGTH, byte_stride / bytes_per_pixel); + + glamor_pixmap_loop(priv, box_x, box_y) { + BoxPtr box = glamor_pixmap_box_at(priv, box_x, box_y); + glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(priv, box_x, box_y); + BoxPtr boxes = in_boxes; + int nbox = in_nbox; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, fbo->tex); + + while (nbox--) { + + /* compute drawable coordinates */ + int x1 = boxes->x1 + dx_dst; + int x2 = boxes->x2 + dx_dst; + int y1 = boxes->y1 + dy_dst; + int y2 = boxes->y2 + dy_dst; + + boxes++; + + if (x1 < box->x1) + x1 = box->x1; + if (box->x2 < x2) + x2 = box->x2; + + if (x2 <= x1) + continue; + + if (y1 < box->y1) + y1 = box->y1; + if (box->y2 < y2) + y2 = box->y2; + + if (y2 <= y1) + continue; + + glPixelStorei(GL_UNPACK_SKIP_ROWS, y1 - dy_dst + dy_src); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1 - dx_dst + dx_src); + + glTexSubImage2D(GL_TEXTURE_2D, 0, + x1 - box->x1, y1 - box->y1, + x2 - x1, y2 - y1, + format, type, + bits); + } + } + + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glamor_put_context(glamor_priv); +} + +/* + * Upload a region of data + */ + +void +glamor_upload_region(PixmapPtr pixmap, RegionPtr region, + int region_x, int region_y, + uint8_t *bits, uint32_t byte_stride) +{ + glamor_upload_boxes(pixmap, RegionRects(region), RegionNumRects(region), + -region_x, -region_y, + 0, 0, + bits, byte_stride); +} + +/* + * Take the data in the pixmap and stuff it back into the FBO + */ +void +glamor_upload_pixmap(PixmapPtr pixmap) +{ + BoxRec box; + + box.x1 = 0; + box.x2 = pixmap->drawable.width; + box.y1 = 0; + box.y2 = pixmap->drawable.height; + glamor_upload_boxes(pixmap, &box, 1, 0, 0, 0, 0, + pixmap->devPrivate.ptr, pixmap->devKind); +} + +/* + * Read stuff from the pixmap FBOs and write to memory + */ +void +glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox, + int dx_src, int dy_src, + int dx_dst, int dy_dst, + uint8_t *bits, uint32_t byte_stride) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap); + int box_x, box_y; + int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3; + GLenum type; + GLenum format; + + glamor_format_for_pixmap(pixmap, &format, &type); + + glamor_get_context(glamor_priv); + + glPixelStorei(GL_PACK_ALIGNMENT, 4); + glPixelStorei(GL_PACK_ROW_LENGTH, byte_stride / bytes_per_pixel); + + glamor_pixmap_loop(priv, box_x, box_y) { + BoxPtr box = glamor_pixmap_box_at(priv, box_x, box_y); + glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(priv, box_x, box_y); + BoxPtr boxes = in_boxes; + int nbox = in_nbox; + + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->fb); + + while (nbox--) { + + /* compute drawable coordinates */ + int x1 = boxes->x1 + dx_src; + int x2 = boxes->x2 + dx_src; + int y1 = boxes->y1 + dy_src; + int y2 = boxes->y2 + dy_src; + + boxes++; + + if (x1 < box->x1) + x1 = box->x1; + if (box->x2 < x2) + x2 = box->x2; + + if (y1 < box->y1) + y1 = box->y1; + if (box->y2 < y2) + y2 = box->y2; + + if (x2 <= x1) + continue; + if (y2 <= y1) + continue; + + glPixelStorei(GL_PACK_SKIP_PIXELS, x1 - dx_src + dx_dst); + glPixelStorei(GL_PACK_SKIP_ROWS, y1 - dy_src + dy_dst); + glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, y2 - y1, format, type, bits); + } + } + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glPixelStorei(GL_PACK_SKIP_ROWS, 0); + glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + glamor_put_context(glamor_priv); +} + +/* + * Read data from the pixmap FBO + */ +void +glamor_download_rect(PixmapPtr pixmap, int x, int y, int w, int h, uint8_t *bits) +{ + BoxRec box; + + box.x1 = x; + box.x2 = x + w; + box.y1 = y; + box.y2 = y + h; + + glamor_download_boxes(pixmap, &box, 1, 0, 0, -x, -y, + bits, PixmapBytePad(w, pixmap->drawable.depth)); +} + +/* + * Pull the data from the FBO down to the pixmap + */ +void +glamor_download_pixmap(PixmapPtr pixmap) +{ + BoxRec box; + + box.x1 = 0; + box.x2 = pixmap->drawable.width; + box.y1 = 0; + box.y2 = pixmap->drawable.height; + + glamor_download_boxes(pixmap, &box, 1, 0, 0, 0, 0, + pixmap->devPrivate.ptr, pixmap->devKind); +} diff --git a/xorg-server/glamor/glamor_transfer.h b/xorg-server/glamor/glamor_transfer.h new file mode 100644 index 000000000..de8186a70 --- /dev/null +++ b/xorg-server/glamor/glamor_transfer.h @@ -0,0 +1,55 @@ +/* + * Copyright © 2014 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _GLAMOR_TRANSFER_H_ +#define _GLAMOR_TRANSFER_H_ + +void +glamor_format_for_pixmap(PixmapPtr pixmap, GLenum *format, GLenum *type); + +void +glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox, + int dx_src, int dy_src, + int dx_dst, int dy_dst, + uint8_t *bits, uint32_t byte_stride); + +void +glamor_upload_region(PixmapPtr pixmap, RegionPtr region, + int region_x, int region_y, + uint8_t *bits, uint32_t byte_stride); + +void +glamor_upload_pixmap(PixmapPtr pixmap); + +void +glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox, + int dx_src, int dy_src, + int dx_dst, int dy_dst, + uint8_t *bits, uint32_t byte_stride); + +void +glamor_download_rect(PixmapPtr pixmap, int x, int y, int w, int h, uint8_t *bits); + +void +glamor_download_pixmap(PixmapPtr pixmap); + +#endif /* _GLAMOR_TRANSFER_H_ */ diff --git a/xorg-server/glamor/glamor_xv.c b/xorg-server/glamor/glamor_xv.c index 17745a4e8..4e60fa3a4 100644 --- a/xorg-server/glamor/glamor_xv.c +++ b/xorg-server/glamor/glamor_xv.c @@ -114,18 +114,6 @@ glamor_init_xv_shader(ScreenPtr screen) glamor_put_context(glamor_priv); } -void -glamor_fini_xv_shader(ScreenPtr screen) -{ - glamor_screen_private *glamor_priv; - - glamor_priv = glamor_get_screen_private(screen); - glamor_get_context(glamor_priv); - - glDeleteProgram(glamor_priv->xv_prog); - glamor_put_context(glamor_priv); -} - #define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v)) #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) @@ -559,6 +547,8 @@ glamor_xv_init(ScreenPtr screen, int num_texture_ports) XF86VideoAdaptorPtr adapt; int i; + glamor_init_xv_shader(screen); + adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + num_texture_ports * (sizeof(glamor_port_private) + sizeof(DevUnion))); if (adapt == NULL) diff --git a/xorg-server/hw/Makefile.am b/xorg-server/hw/Makefile.am index 6c2cc6bd4..19895dc77 100644 --- a/xorg-server/hw/Makefile.am +++ b/xorg-server/hw/Makefile.am @@ -26,6 +26,10 @@ if XQUARTZ XQUARTZ_SUBDIRS = xquartz endif +if XWAYLAND +XWAYLAND_SUBDIRS = xwayland +endif + SUBDIRS = \ $(XORG_SUBDIRS) \ $(XWIN_SUBDIRS) \ @@ -33,9 +37,10 @@ SUBDIRS = \ $(XNEST_SUBDIRS) \ $(DMX_SUBDIRS) \ $(KDRIVE_SUBDIRS) \ - $(XQUARTZ_SUBDIRS) + $(XQUARTZ_SUBDIRS) \ + $(XWAYLAND_SUBDIRS) -DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive +DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland relink: $(AM_V_at)for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink || exit 1 ; done diff --git a/xorg-server/hw/dmx/Makefile.am b/xorg-server/hw/dmx/Makefile.am index a05af139e..eef84cb66 100644 --- a/xorg-server/hw/dmx/Makefile.am +++ b/xorg-server/hw/dmx/Makefile.am @@ -65,7 +65,6 @@ Xdmx_SOURCES = dmx.c \ dmxwindow.c \ dmxwindow.h \ $(top_srcdir)/mi/miinitext.c \ - $(top_srcdir)/fb/fbcmap_mi.c \ $(GLX_SRCS) diff --git a/xorg-server/hw/kdrive/ephyr/ephyr_glamor_glx.c b/xorg-server/hw/kdrive/ephyr/ephyr_glamor_glx.c index 9903cc772..eaf565496 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyr_glamor_glx.c +++ b/xorg-server/hw/kdrive/ephyr/ephyr_glamor_glx.c @@ -313,7 +313,6 @@ ephyr_glamor_get_visual(void) GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, 1, - GLX_VISUAL_ID, DefaultVisual(dpy, DefaultScreen(dpy)), None }; int event_base = 0, error_base = 0, nelements; diff --git a/xorg-server/hw/kdrive/ephyr/hostx.c b/xorg-server/hw/kdrive/ephyr/hostx.c index 4f48770a6..435919e0a 100644 --- a/xorg-server/hw/kdrive/ephyr/hostx.c +++ b/xorg-server/hw/kdrive/ephyr/hostx.c @@ -734,13 +734,16 @@ hostx_screen_init(KdScreenInfo *screen, scrpriv->win_width = width; scrpriv->win_height = height; +#ifdef GLAMOR if (ephyr_glamor) { *bytes_per_line = 0; *bits_per_pixel = 0; ephyr_glamor_set_window_size(scrpriv->glamor, scrpriv->win_width, scrpriv->win_height); return NULL; - } else if (host_depth_matches_server(scrpriv)) { + } else +#endif + if (host_depth_matches_server(scrpriv)) { *bytes_per_line = scrpriv->ximg->stride; *bits_per_pixel = scrpriv->ximg->bpp; diff --git a/xorg-server/hw/kdrive/src/Makefile.am b/xorg-server/hw/kdrive/src/Makefile.am index 5799ddbdb..d69f0dd99 100644 --- a/xorg-server/hw/kdrive/src/Makefile.am +++ b/xorg-server/hw/kdrive/src/Makefile.am @@ -4,7 +4,7 @@ AM_CPPFLAGS = \ AM_CFLAGS = -DHAVE_DIX_CONFIG_H -noinst_LTLIBRARIES = libkdrive.la libkdrivestubs.la +noinst_LTLIBRARIES = libkdrive.la if XV KDRIVE_XV_SOURCES = \ @@ -23,6 +23,3 @@ libkdrive_la_SOURCES = \ kshadow.c \ $(KDRIVE_XV_SOURCES) \ $(top_srcdir)/mi/miinitext.c - -libkdrivestubs_la_SOURCES = \ - $(top_srcdir)/fb/fbcmap_mi.c diff --git a/xorg-server/hw/vfb/Makefile.am b/xorg-server/hw/vfb/Makefile.am index 9f4992c8b..f0f9fee47 100644 --- a/xorg-server/hw/vfb/Makefile.am +++ b/xorg-server/hw/vfb/Makefile.am @@ -1,7 +1,6 @@ SUBDIRS = man bin_PROGRAMS = Xvfb -noinst_LIBRARIES = libfbcmap.a AM_CFLAGS = -DHAVE_DIX_CONFIG_H \ $(XVFBMODULES_CFLAGS) \ @@ -9,20 +8,16 @@ AM_CFLAGS = -DHAVE_DIX_CONFIG_H \ SRCS = InitInput.c \ InitOutput.c \ - $(top_srcdir)/Xext/dpmsstubs.c \ - $(top_srcdir)/Xi/stubs.c \ $(top_srcdir)/mi/miinitext.c -libfbcmap_a_CFLAGS = $(AM_CFLAGS) -libfbcmap_a_SOURCES = $(top_srcdir)/fb/fbcmap_mi.c - Xvfb_SOURCES = $(SRCS) XVFB_LIBS = \ @XVFB_LIBS@ \ - libfbcmap.a \ $(MAIN_LIB) \ - $(XSERVER_LIBS) + $(XSERVER_LIBS) \ + $(top_builddir)/Xext/libXextdpmsstubs.la \ + $(top_builddir)/Xi/libXistubs.la Xvfb_LDADD = $(XVFB_LIBS) $(XVFB_SYS_LIBS) $(XSERVER_SYS_LIBS) Xvfb_DEPENDENCIES = $(XVFB_LIBS) diff --git a/xorg-server/hw/xfree86/.gitignore b/xorg-server/hw/xfree86/.gitignore index 997a94efe..fb6830b2c 100644 --- a/xorg-server/hw/xfree86/.gitignore +++ b/xorg-server/hw/xfree86/.gitignore @@ -1,4 +1,5 @@ Xorg +Xorg.sh xorg.conf.example sdksyms.c sdksyms.dep diff --git a/xorg-server/hw/xfree86/Makefile.am b/xorg-server/hw/xfree86/Makefile.am index 18fa99b08..c5992c372 100644 --- a/xorg-server/hw/xfree86/Makefile.am +++ b/xorg-server/hw/xfree86/Makefile.am @@ -89,7 +89,7 @@ endif BUILT_SOURCES = xorg.conf.example DISTCLEANFILES = xorg.conf.example -EXTRA_DIST = xorgconf.cpp Xorg.sh.in +EXTRA_DIST = xorgconf.cpp # Without logdir, X will post an error on the terminal and will not start install-data-local: @@ -105,6 +105,7 @@ if INSTALL_SETUID chmod u+s $(DESTDIR)$(bindir)/Xorg endif if SUID_WRAPPER + $(MKDIR_P) $(DESTDIR)$(SUID_WRAPPER_DIR) mv $(DESTDIR)$(bindir)/Xorg $(DESTDIR)$(SUID_WRAPPER_DIR)/Xorg.bin ${INSTALL} -m 755 Xorg.sh $(DESTDIR)$(bindir)/Xorg -chown root $(DESTDIR)$(SUID_WRAPPER_DIR)/Xorg.wrap && chmod u+s $(DESTDIR)$(SUID_WRAPPER_DIR)/Xorg.wrap diff --git a/xorg-server/hw/xfree86/common/xf86Events.c b/xorg-server/hw/xfree86/common/xf86Events.c index 06af73903..35a673d15 100644 --- a/xorg-server/hw/xfree86/common/xf86Events.c +++ b/xorg-server/hw/xfree86/common/xf86Events.c @@ -56,6 +56,7 @@ #include <X11/X.h> #include <X11/Xpoll.h> #include <X11/Xproto.h> +#include <X11/Xatom.h> #include "misc.h" #include "compiler.h" #include "xf86.h" @@ -431,6 +432,29 @@ xf86EnableInputDeviceForVTSwitch(InputInfoPtr pInfo) pInfo->flags &= ~XI86_DEVICE_DISABLED; } +/* + * xf86UpdateHasVTProperty -- + * Update a flag property on the root window to say whether the server VT + * is currently the active one as some clients need to know this. + */ +static void +xf86UpdateHasVTProperty(Bool hasVT) +{ + Atom property_name; + int32_t value = hasVT ? 1 : 0; + int i; + + property_name = MakeAtom(HAS_VT_ATOM_NAME, sizeof(HAS_VT_ATOM_NAME) - 1, + FALSE); + if (property_name == BAD_RESOURCE) + FatalError("Failed to retrieve \"HAS_VT\" atom\n"); + for (i = 0; i < xf86NumScreens; i++) { + ChangeWindowProperty(xf86ScrnToScreen(xf86Screens[i])->root, + property_name, XA_INTEGER, 32, + PropModeReplace, 1, &value, TRUE); + } +} + void xf86VTLeave(void) { @@ -490,6 +514,8 @@ xf86VTLeave(void) if (xorgHWAccess) xf86DisableIO(); + xf86UpdateHasVTProperty(FALSE); + return; switch_failed: @@ -574,6 +600,8 @@ xf86VTEnter(void) xf86platformVTProbe(); #endif + xf86UpdateHasVTProperty(TRUE); + OsReleaseSIGIO(); } diff --git a/xorg-server/hw/xfree86/common/xf86Globals.c b/xorg-server/hw/xfree86/common/xf86Globals.c index 7df7a80c4..984c39bca 100644 --- a/xorg-server/hw/xfree86/common/xf86Globals.c +++ b/xorg-server/hw/xfree86/common/xf86Globals.c @@ -143,7 +143,7 @@ const char *xf86ConfigFile = NULL; const char *xf86ConfigDir = NULL; const char *xf86ModulePath = DEFAULT_MODULE_PATH; MessageType xf86ModPathFrom = X_DEFAULT; -const char *xf86LogFile = DEFAULT_LOGPREFIX; +const char *xf86LogFile = DEFAULT_LOGDIR "/" DEFAULT_LOGPREFIX; MessageType xf86LogFileFrom = X_DEFAULT; Bool xf86LogFileWasOpened = FALSE; serverLayoutRec xf86ConfigLayout = { NULL, }; diff --git a/xorg-server/hw/xfree86/common/xf86Helper.c b/xorg-server/hw/xfree86/common/xf86Helper.c index 12a877159..e2b32a074 100644 --- a/xorg-server/hw/xfree86/common/xf86Helper.c +++ b/xorg-server/hw/xfree86/common/xf86Helper.c @@ -1217,16 +1217,45 @@ xf86ErrorF(const char *format, ...) va_end(ap); } +/* Note temporarily modifies the passed in buffer! */ +static void xf86_mkdir_p(char *path) +{ + char *sep = path; + + while ((sep = strchr(sep + 1, '/'))) { + *sep = 0; + (void)mkdir(path, 0777); + *sep = '/'; + } + (void)mkdir(path, 0777); +} + void xf86LogInit(void) { - char *lf = NULL; + char *env, *lf = NULL; + char buf[PATH_MAX]; #define LOGSUFFIX ".log" #define LOGOLDSUFFIX ".old" /* Get the log file name */ if (xf86LogFileFrom == X_DEFAULT) { + /* When not running as root, we won't be able to write to /var/log */ + if (geteuid() != 0) { + if ((env = getenv("XDG_DATA_HOME"))) + snprintf(buf, sizeof(buf), "%s/%s", env, + DEFAULT_XDG_DATA_HOME_LOGDIR); + else if ((env = getenv("HOME"))) + snprintf(buf, sizeof(buf), "%s/%s/%s", env, + DEFAULT_XDG_DATA_HOME, DEFAULT_XDG_DATA_HOME_LOGDIR); + + if (env) { + xf86_mkdir_p(buf); + strlcat(buf, "/" DEFAULT_LOGPREFIX, sizeof(buf)); + xf86LogFile = buf; + } + } /* Append the display number and ".log" */ if (asprintf(&lf, "%s%%s" LOGSUFFIX, xf86LogFile) == -1) FatalError("Cannot allocate space for the log file name\n"); diff --git a/xorg-server/hw/xfree86/common/xf86Init.c b/xorg-server/hw/xfree86/common/xf86Init.c index 4579ff591..5a45004f5 100644 --- a/xorg-server/hw/xfree86/common/xf86Init.c +++ b/xorg-server/hw/xfree86/common/xf86Init.c @@ -387,6 +387,11 @@ InstallSignalHandlers(void) } } +/* The memory storing the initial value of the XFree86_has_VT root window + * property. This has to remain available until server start-up, so we just + * use a global. */ +static CARD32 HasVTValue = 1; + /* * InitOutput -- * Initialize screenInfo for all actually accessible framebuffers. @@ -731,7 +736,9 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) if (xf86Info.vtno >= 0) { #define VT_ATOM_NAME "XFree86_VT" Atom VTAtom = -1; + Atom HasVTAtom = -1; CARD32 *VT = NULL; + CARD32 *HasVT = &HasVTValue; int ret; /* This memory needs to stay available until the screen has been @@ -744,6 +751,8 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) *VT = xf86Info.vtno; VTAtom = MakeAtom(VT_ATOM_NAME, sizeof(VT_ATOM_NAME) - 1, TRUE); + HasVTAtom = MakeAtom(HAS_VT_ATOM_NAME, + sizeof(HAS_VT_ATOM_NAME) - 1, TRUE); for (i = 0, ret = Success; i < xf86NumScreens && ret == Success; i++) { @@ -751,9 +760,14 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) xf86RegisterRootWindowProperty(xf86Screens[i]->scrnIndex, VTAtom, XA_INTEGER, 32, 1, VT); + if (ret == Success) + ret = xf86RegisterRootWindowProperty(xf86Screens[i] + ->scrnIndex, + HasVTAtom, XA_INTEGER, + 32, 1, HasVT); if (ret != Success) xf86DrvMsg(xf86Screens[i]->scrnIndex, X_WARNING, - "Failed to register VT property\n"); + "Failed to register VT properties\n"); } } diff --git a/xorg-server/hw/xfree86/common/xf86Module.h b/xorg-server/hw/xfree86/common/xf86Module.h index e8c24f26c..62ac95d5a 100644 --- a/xorg-server/hw/xfree86/common/xf86Module.h +++ b/xorg-server/hw/xfree86/common/xf86Module.h @@ -80,7 +80,7 @@ typedef enum { * mask is 0xFFFF0000. */ #define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4) -#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(16, 0) +#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(17, 0) #define ABI_XINPUT_VERSION SET_ABI_VERSION(21, 0) #define ABI_EXTENSION_VERSION SET_ABI_VERSION(8, 0) #define ABI_FONT_VERSION SET_ABI_VERSION(0, 6) diff --git a/xorg-server/hw/xfree86/common/xf86Privstr.h b/xorg-server/hw/xfree86/common/xf86Privstr.h index f7a9c9f1c..410ef17ac 100644 --- a/xorg-server/hw/xfree86/common/xf86Privstr.h +++ b/xorg-server/hw/xfree86/common/xf86Privstr.h @@ -163,4 +163,8 @@ typedef struct _RootWinProp { #define WSCONS 32 #endif +/* Root window property to tell clients whether our VT is currently active. + * Name chosen to match the "XFree86_VT" property. */ +#define HAS_VT_ATOM_NAME "XFree86_has_VT" + #endif /* _XF86PRIVSTR_H */ diff --git a/xorg-server/hw/xfree86/dixmods/Makefile.am b/xorg-server/hw/xfree86/dixmods/Makefile.am index 3c43640ec..dd076e421 100644 --- a/xorg-server/hw/xfree86/dixmods/Makefile.am +++ b/xorg-server/hw/xfree86/dixmods/Makefile.am @@ -19,12 +19,12 @@ AM_CPPFLAGS = @XORG_INCS@ \ libfb_la_LDFLAGS = -module -avoid-version $(LD_NO_UNDEFINED_FLAG) libfb_la_LIBADD = $(top_builddir)/fb/libfb.la -libfb_la_SOURCES = $(top_builddir)/fb/fbcmap_mi.c fbmodule.c +libfb_la_SOURCES = fbmodule.c libfb_la_CFLAGS = $(AM_CFLAGS) libwfb_la_LDFLAGS = -module -avoid-version $(LD_NO_UNDEFINED_FLAG) libwfb_la_LIBADD = $(top_builddir)/fb/libwfb.la -libwfb_la_SOURCES = $(top_builddir)/fb/fbcmap_mi.c fbmodule.c +libwfb_la_SOURCES = fbmodule.c libwfb_la_CFLAGS = $(AM_CFLAGS) -DFB_ACCESS_WRAPPER libglx_la_LDFLAGS = -module -avoid-version $(LD_NO_UNDEFINED_FLAG) diff --git a/xorg-server/hw/xfree86/man/Xorg.man b/xorg-server/hw/xfree86/man/Xorg.man index 0cd5a1068..3ff6aef89 100644 --- a/xorg-server/hw/xfree86/man/Xorg.man +++ b/xorg-server/hw/xfree86/man/Xorg.man @@ -301,9 +301,11 @@ Use the file called .I filename as the .B Xorg -server log file. The default log file is +server log file. The default log file when running as root is .BI __logdir__/Xorg. n .log -on most platforms, where +and for non root it is +.BI $XDG_DATA_HOME/xorg/Xorg. n .log +where .I n is the display number of the .B Xorg diff --git a/xorg-server/hw/xfree86/man/xorg.conf.man b/xorg-server/hw/xfree86/man/xorg.conf.man index 85f9f2ee1..6d2652e84 100644 --- a/xorg-server/hw/xfree86/man/xorg.conf.man +++ b/xorg-server/hw/xfree86/man/xorg.conf.man @@ -442,11 +442,15 @@ __modulepath__ .TP 7 .BI "LogFile \*q" path \*q sets the name of the Xorg server log file. -The default log file name is +The default log file name when running as root is .PP .RS 11 .RI __logdir__/Xorg. <n> .log .RE +and for non root it is +.RS 11 +.RI $XDG_DATA_HOME/xorg/Xorg. <n> .log +.RE .PP .RS 7 where diff --git a/xorg-server/hw/xfree86/modes/xf86Crtc.h b/xorg-server/hw/xfree86/modes/xf86Crtc.h index c127d78af..5407deb0e 100644 --- a/xorg-server/hw/xfree86/modes/xf86Crtc.h +++ b/xorg-server/hw/xfree86/modes/xf86Crtc.h @@ -186,13 +186,13 @@ typedef struct _xf86CrtcFuncs { /** * Load monochrome image */ - void + Bool (*load_cursor_image) (xf86CrtcPtr crtc, CARD8 *image); /** * Load ARGB image */ - void + Bool (*load_cursor_argb) (xf86CrtcPtr crtc, CARD32 *image); /** diff --git a/xorg-server/hw/xfree86/modes/xf86Cursors.c b/xorg-server/hw/xfree86/modes/xf86Cursors.c index 2b0db3492..10ef6f6d4 100644 --- a/xorg-server/hw/xfree86/modes/xf86Cursors.c +++ b/xorg-server/hw/xfree86/modes/xf86Cursors.c @@ -211,7 +211,7 @@ set_bit(CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y, Bool mask) /* * Load a two color cursor into a driver that supports only ARGB cursors */ -static void +static Bool xf86_crtc_convert_cursor_to_argb(xf86CrtcPtr crtc, unsigned char *src) { ScrnInfoPtr scrn = crtc->scrn; @@ -244,7 +244,7 @@ xf86_crtc_convert_cursor_to_argb(xf86CrtcPtr crtc, unsigned char *src) bits = 0; cursor_image[y * cursor_info->MaxWidth + x] = bits; } - crtc->funcs->load_cursor_argb(crtc, cursor_image); + return crtc->funcs->load_cursor_argb(crtc, cursor_image); } /* @@ -415,7 +415,7 @@ xf86_set_cursor_position(ScrnInfoPtr scrn, int x, int y) /* * Load a two-color cursor into a crtc, performing rotation as needed */ -static void +static Bool xf86_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *src) { ScrnInfoPtr scrn = crtc->scrn; @@ -450,13 +450,13 @@ xf86_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *src) set_bit(cursor_image, cursor_info, x, y, TRUE); } } - crtc->funcs->load_cursor_image(crtc, cursor_image); + return crtc->funcs->load_cursor_image(crtc, cursor_image); } /* * Load a cursor image into all active CRTCs */ -static void +static Bool xf86_load_cursor_image(ScrnInfoPtr scrn, unsigned char *src) { xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); @@ -466,12 +466,17 @@ xf86_load_cursor_image(ScrnInfoPtr scrn, unsigned char *src) xf86CrtcPtr crtc = xf86_config->crtc[c]; if (crtc->enabled) { - if (crtc->funcs->load_cursor_image) - xf86_crtc_load_cursor_image(crtc, src); - else if (crtc->funcs->load_cursor_argb) - xf86_crtc_convert_cursor_to_argb(crtc, src); + if (crtc->funcs->load_cursor_image) { + if (!xf86_crtc_load_cursor_image(crtc, src)) + return FALSE; + } else if (crtc->funcs->load_cursor_argb) { + if (!xf86_crtc_convert_cursor_to_argb(crtc, src)) + return FALSE; + } else + return FALSE; } } + return TRUE; } static Bool @@ -516,7 +521,7 @@ xf86_use_hw_cursor_argb(ScreenPtr screen, CursorPtr cursor) return TRUE; } -static void +static Bool xf86_crtc_load_cursor_argb(xf86CrtcPtr crtc, CursorPtr cursor) { ScrnInfoPtr scrn = crtc->scrn; @@ -544,10 +549,10 @@ xf86_crtc_load_cursor_argb(xf86CrtcPtr crtc, CursorPtr cursor) cursor_image[y * image_width + x] = bits; } - crtc->funcs->load_cursor_argb(crtc, cursor_image); + return crtc->funcs->load_cursor_argb(crtc, cursor_image); } -static void +static Bool xf86_load_cursor_argb(ScrnInfoPtr scrn, CursorPtr cursor) { xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); @@ -557,8 +562,10 @@ xf86_load_cursor_argb(ScrnInfoPtr scrn, CursorPtr cursor) xf86CrtcPtr crtc = xf86_config->crtc[c]; if (crtc->enabled) - xf86_crtc_load_cursor_argb(crtc, cursor); + if (!xf86_crtc_load_cursor_argb(crtc, cursor)) + return FALSE; } + return TRUE; } Bool @@ -608,6 +615,8 @@ xf86_cursors_init(ScreenPtr screen, int max_width, int max_height, int flags) * Called when anything on the screen is reconfigured. * * Reloads cursor images as needed, then adjusts cursor positions + * @note We assume that all hardware cursors to be loaded have already been + * found to be usable by the hardware. */ void diff --git a/xorg-server/hw/xfree86/os-support/linux/systemd-logind.c b/xorg-server/hw/xfree86/os-support/linux/systemd-logind.c index 62858b062..ed670a88c 100644 --- a/xorg-server/hw/xfree86/os-support/linux/systemd-logind.c +++ b/xorg-server/hw/xfree86/os-support/linux/systemd-logind.c @@ -310,10 +310,31 @@ message_filter(DBusConnection * connection, DBusMessage * message, void *data) dbus_int32_t major, minor; char *pause_str; - if (strcmp(dbus_message_get_path(message), info->session) != 0) + dbus_error_init(&error); + + if (dbus_message_is_signal(message, + "org.freedesktop.DBus", "NameOwnerChanged")) { + char *name, *old_owner, *new_owner; + + dbus_message_get_args(message, &error, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &old_owner, + DBUS_TYPE_STRING, &new_owner, DBUS_TYPE_INVALID); + if (dbus_error_is_set(&error)) { + LogMessage(X_ERROR, "systemd-logind: NameOwnerChanged: %s\n", + error.message); + dbus_error_free(&error); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (name && strcmp(name, "org.freedesktop.login1") == 0) + FatalError("systemd-logind disappeared (stopped/restarted?)\n"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } - dbus_error_init(&error); + if (strcmp(dbus_message_get_path(message), info->session) != 0) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; if (dbus_message_is_signal(message, "org.freedesktop.login1.Session", "PauseDevice")) { @@ -472,6 +493,15 @@ connect_hook(DBusConnection *connection, void *data) goto cleanup; } + dbus_bus_add_match(connection, + "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',path='/org/freedesktop/DBus'", + &error); + if (dbus_error_is_set(&error)) { + LogMessage(X_ERROR, "systemd-logind: could not add match: %s\n", + error.message); + goto cleanup; + } + /* * HdG: This is not useful with systemd <= 208 since the signal only * contains invalidated property names there, rather than property, val diff --git a/xorg-server/hw/xfree86/parser/DRI.c b/xorg-server/hw/xfree86/parser/DRI.c index ad053f746..6be32d7ea 100644 --- a/xorg-server/hw/xfree86/parser/DRI.c +++ b/xorg-server/hw/xfree86/parser/DRI.c @@ -31,6 +31,7 @@ #include <xorg-config.h> #endif +#include "os.h" #include "xf86Parser.h" #include "xf86tokens.h" #include "Configint.h" diff --git a/xorg-server/hw/xfree86/parser/Extensions.c b/xorg-server/hw/xfree86/parser/Extensions.c index b5ba72e5f..a6fcb56f0 100644 --- a/xorg-server/hw/xfree86/parser/Extensions.c +++ b/xorg-server/hw/xfree86/parser/Extensions.c @@ -35,6 +35,7 @@ #include <xorg-config.h> #endif +#include "os.h" #include "xf86Parser.h" #include "xf86tokens.h" #include "Configint.h" diff --git a/xorg-server/hw/xfree86/ramdac/IBM.c b/xorg-server/hw/xfree86/ramdac/IBM.c index bc716231a..872d3d4e7 100644 --- a/xorg-server/hw/xfree86/ramdac/IBM.c +++ b/xorg-server/hw/xfree86/ramdac/IBM.c @@ -570,7 +570,7 @@ IBMramdac640SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) (*ramdacPtr->WriteData) (pScrn, bg); } -static void +static Bool IBMramdac526LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) { RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn); @@ -582,9 +582,10 @@ IBMramdac526LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) */ for (i = 0; i < 1024; i++) (*ramdacPtr->WriteDAC) (pScrn, IBMRGB_curs_array + i, 0x00, (*src++)); + return TRUE; } -static void +static Bool IBMramdac640LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) { RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn); @@ -596,6 +597,7 @@ IBMramdac640LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) */ for (i = 0; i < 1024; i++) (*ramdacPtr->WriteDAC) (pScrn, RGB640_CURS_WRITE + i, 0x00, (*src++)); + return TRUE; } static Bool diff --git a/xorg-server/hw/xfree86/ramdac/TI.c b/xorg-server/hw/xfree86/ramdac/TI.c index 393b774d4..7d4e0d796 100644 --- a/xorg-server/hw/xfree86/ramdac/TI.c +++ b/xorg-server/hw/xfree86/ramdac/TI.c @@ -642,7 +642,7 @@ TIramdacSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_COLOR, 0, (fg & 0x000000ff)); } -static void +static Bool TIramdacLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) { RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn); @@ -657,6 +657,7 @@ TIramdacLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) /* NOT_DONE: might need a delay here */ (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_RAM_DATA, 0, *(src++)); } + return TRUE; } static Bool diff --git a/xorg-server/hw/xfree86/ramdac/xf86Cursor.c b/xorg-server/hw/xfree86/ramdac/xf86Cursor.c index 860704e1c..fac682210 100644 --- a/xorg-server/hw/xfree86/ramdac/xf86Cursor.c +++ b/xorg-server/hw/xfree86/ramdac/xf86Cursor.c @@ -352,12 +352,13 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs, (*ScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, NullCursor, x, y); - xf86SetCursor(pScreen, cursor, x, y); - ScreenPriv->SWCursor = FALSE; - ScreenPriv->isUp = TRUE; + if (xf86SetCursor(pScreen, cursor, x, y)) { + ScreenPriv->SWCursor = FALSE; + ScreenPriv->isUp = TRUE; - miPointerSetWaitForUpdate(pScreen, !infoPtr->pScrn->silkenMouse); - return; + miPointerSetWaitForUpdate(pScreen, !infoPtr->pScrn->silkenMouse); + return; + } } miPointerSetWaitForUpdate(pScreen, TRUE); diff --git a/xorg-server/hw/xfree86/ramdac/xf86Cursor.h b/xorg-server/hw/xfree86/ramdac/xf86Cursor.h index 5658e7b30..1ecbdcd8d 100644 --- a/xorg-server/hw/xfree86/ramdac/xf86Cursor.h +++ b/xorg-server/hw/xfree86/ramdac/xf86Cursor.h @@ -12,7 +12,7 @@ typedef struct _xf86CursorInfoRec { int MaxHeight; void (*SetCursorColors) (ScrnInfoPtr pScrn, int bg, int fg); void (*SetCursorPosition) (ScrnInfoPtr pScrn, int x, int y); - void (*LoadCursorImage) (ScrnInfoPtr pScrn, unsigned char *bits); + Bool (*LoadCursorImage) (ScrnInfoPtr pScrn, unsigned char *bits); void (*HideCursor) (ScrnInfoPtr pScrn); void (*ShowCursor) (ScrnInfoPtr pScrn); unsigned char *(*RealizeCursor) (struct _xf86CursorInfoRec *, CursorPtr); @@ -20,7 +20,7 @@ typedef struct _xf86CursorInfoRec { #ifdef ARGB_CURSOR Bool (*UseHWCursorARGB) (ScreenPtr, CursorPtr); - void (*LoadCursorARGB) (ScrnInfoPtr, CursorPtr); + Bool (*LoadCursorARGB) (ScrnInfoPtr, CursorPtr); #endif } xf86CursorInfoRec, *xf86CursorInfoPtr; diff --git a/xorg-server/hw/xfree86/ramdac/xf86CursorPriv.h b/xorg-server/hw/xfree86/ramdac/xf86CursorPriv.h index a5d2aabc3..f34c1c7fc 100644 --- a/xorg-server/hw/xfree86/ramdac/xf86CursorPriv.h +++ b/xorg-server/hw/xfree86/ramdac/xf86CursorPriv.h @@ -37,7 +37,7 @@ typedef struct { void *transparentData; } xf86CursorScreenRec, *xf86CursorScreenPtr; -void xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y); +Bool xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y); void xf86SetTransparentCursor(ScreenPtr pScreen); void xf86MoveCursor(ScreenPtr pScreen, int x, int y); void xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed); diff --git a/xorg-server/hw/xfree86/ramdac/xf86HWCurs.c b/xorg-server/hw/xfree86/ramdac/xf86HWCurs.c index 3b69698db..0b5caa20a 100644 --- a/xorg-server/hw/xfree86/ramdac/xf86HWCurs.c +++ b/xorg-server/hw/xfree86/ramdac/xf86HWCurs.c @@ -119,7 +119,7 @@ xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr) return TRUE; } -void +Bool xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) { xf86CursorScreenPtr ScreenPriv = @@ -130,7 +130,7 @@ xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) if (pCurs == NullCursor) { (*infoPtr->HideCursor) (infoPtr->pScrn); - return; + return TRUE; } bits = @@ -152,18 +152,21 @@ xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) (*infoPtr->HideCursor) (infoPtr->pScrn); #ifdef ARGB_CURSOR - if (pCurs->bits->argb && infoPtr->LoadCursorARGB) - (*infoPtr->LoadCursorARGB) (infoPtr->pScrn, pCurs); - else + if (pCurs->bits->argb && infoPtr->LoadCursorARGB) { + if (!(*infoPtr->LoadCursorARGB) (infoPtr->pScrn, pCurs)) + return FALSE; + } else #endif if (bits) - (*infoPtr->LoadCursorImage) (infoPtr->pScrn, bits); + if (!(*infoPtr->LoadCursorImage) (infoPtr->pScrn, bits)) + return FALSE; xf86RecolorCursor(pScreen, pCurs, 1); (*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, y); (*infoPtr->ShowCursor) (infoPtr->pScrn); + return TRUE; } void diff --git a/xorg-server/hw/xnest/Makefile.am b/xorg-server/hw/xnest/Makefile.am index 3c099cd6b..eb550c0f7 100644 --- a/xorg-server/hw/xnest/Makefile.am +++ b/xorg-server/hw/xnest/Makefile.am @@ -1,7 +1,6 @@ SUBDIRS = man bin_PROGRAMS = Xnest -noinst_LIBRARIES = libfbcmap.a AM_CFLAGS = -DHAVE_XNEST_CONFIG_H \ $(DIX_CFLAGS) \ @@ -42,16 +41,12 @@ SRCS = Args.c \ XNPixmap.h \ XNWindow.h \ xnest-config.h \ - $(top_srcdir)/Xext/dpmsstubs.c \ - $(top_srcdir)/Xi/stubs.c \ $(top_srcdir)/mi/miinitext.c -libfbcmap_a_SOURCES = $(top_srcdir)/fb/fbcmap_mi.c -libfbcmap_a_CFLAGS = $(AM_CFLAGS) - XNEST_LIBS = \ @XNEST_LIBS@ \ - libfbcmap.a + $(top_builddir)/Xext/libXextdpmsstubs.la \ + $(top_builddir)/Xi/libXistubs.la Xnest_SOURCES = $(SRCS) diff --git a/xorg-server/hw/xquartz/Makefile.am b/xorg-server/hw/xquartz/Makefile.am index 2ca953cf9..4da896d76 100644 --- a/xorg-server/hw/xquartz/Makefile.am +++ b/xorg-server/hw/xquartz/Makefile.am @@ -20,7 +20,6 @@ SUBDIRS = bundle . $(GL_DIR) xpr pbproxy mach-startup man DIST_SUBDIRS = bundle . GL xpr pbproxy mach-startup man libXquartz_la_SOURCES = \ - $(top_srcdir)/fb/fbcmap_mi.c \ $(top_srcdir)/mi/miinitext.c \ X11Application.m \ X11Controller.m \ diff --git a/xorg-server/hw/xquartz/X11Controller.m b/xorg-server/hw/xquartz/X11Controller.m index 5445c6f3a..022e83258 100644 --- a/xorg-server/hw/xquartz/X11Controller.m +++ b/xorg-server/hw/xquartz/X11Controller.m @@ -942,9 +942,8 @@ extern char *bundle_id_prefix; /* shutdown the X server, it will exit () for us. */ DarwinSendDDXEvent(kXquartzQuit, 0); - /* In case it doesn't, exit anyway after a while. */ - remain = 10000000; - while ((remain = usleep(remain)) > 0) ; + /* In case it doesn't, exit anyway after 5s. */ + [NSThread sleepForTimeInterval:5.0]; exit(1); } diff --git a/xorg-server/hw/xwayland/.gitignore b/xorg-server/hw/xwayland/.gitignore new file mode 100644 index 000000000..c54ba2de9 --- /dev/null +++ b/xorg-server/hw/xwayland/.gitignore @@ -0,0 +1,3 @@ +Xwayland +drm-client-protocol.h +drm-protocol.c diff --git a/xorg-server/hw/xwayland/Makefile.am b/xorg-server/hw/xwayland/Makefile.am new file mode 100644 index 000000000..36e6127df --- /dev/null +++ b/xorg-server/hw/xwayland/Makefile.am @@ -0,0 +1,30 @@ +bin_PROGRAMS = Xwayland + +Xwayland_CFLAGS = \ + -I$(top_srcdir)/dri3 \ + -DHAVE_DIX_CONFIG_H \ + $(XWAYLANDMODULES_CFLAGS) \ + $(DIX_CFLAGS) + +Xwayland_SOURCES = \ + xwayland.c \ + xwayland-input.c \ + xwayland-cursor.c \ + xwayland-shm.c \ + xwayland-output.c \ + xwayland-cvt.c \ + xwayland.h \ + $(top_srcdir)/Xext/dpmsstubs.c \ + $(top_srcdir)/Xi/stubs.c \ + $(top_srcdir)/mi/miinitext.c + +Xwayland_LDADD = \ + $(XWAYLAND_LIBS) \ + $(XWAYLAND_SYS_LIBS) \ + $(XSERVER_SYS_LIBS) +Xwayland_DEPENDENCIES = $(XWAYLAND_LIBS) +Xwayland_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG) + + +relink: + $(AM_V_at)rm -f Xwayland$(EXEEXT) && $(MAKE) Xwayland$(EXEEXT) diff --git a/xorg-server/hw/xwayland/xwayland-cursor.c b/xorg-server/hw/xwayland/xwayland-cursor.c new file mode 100644 index 000000000..5a9d1fe70 --- /dev/null +++ b/xorg-server/hw/xwayland/xwayland-cursor.c @@ -0,0 +1,193 @@ +/* + * Copyright © 2014 Intel Corporation + * Copyright © 2011 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of the + * copyright holders not be used in advertising or publicity + * pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "xwayland.h" + +#include <mipointer.h> + +static DevPrivateKeyRec xwl_cursor_private_key; + +static void +expand_source_and_mask(CursorPtr cursor, CARD32 *data) +{ + CARD32 *p, d, fg, bg; + CursorBitsPtr bits = cursor->bits; + int x, y, stride, i, bit; + + p = data; + fg = ((cursor->foreRed & 0xff00) << 8) | + (cursor->foreGreen & 0xff00) | (cursor->foreGreen >> 8); + bg = ((cursor->backRed & 0xff00) << 8) | + (cursor->backGreen & 0xff00) | (cursor->backGreen >> 8); + stride = (bits->width / 8 + 3) & ~3; + for (y = 0; y < bits->height; y++) + for (x = 0; x < bits->width; x++) { + i = y * stride + x / 8; + bit = 1 << (x & 7); + if (bits->source[i] & bit) + d = fg; + else + d = bg; + if (bits->mask[i] & bit) + d |= 0xff000000; + else + d = 0x00000000; + + *p++ = d; + } +} + +static Bool +xwl_realize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor) +{ + PixmapPtr pixmap; + + pixmap = xwl_shm_create_pixmap(screen, cursor->bits->width, + cursor->bits->height, 32, 0); + dixSetPrivate(&cursor->devPrivates, &xwl_cursor_private_key, pixmap); + + return TRUE; +} + +static Bool +xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor) +{ + PixmapPtr pixmap; + + pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key); + + return xwl_shm_destroy_pixmap(pixmap); +} + +void +xwl_seat_set_cursor(struct xwl_seat *xwl_seat) +{ + PixmapPtr pixmap; + CursorPtr cursor; + int stride; + + if (!xwl_seat->wl_pointer) + return; + + if (!xwl_seat->x_cursor) { + wl_pointer_set_cursor(xwl_seat->wl_pointer, + xwl_seat->pointer_enter_serial, NULL, 0, 0); + return; + } + + cursor = xwl_seat->x_cursor; + pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key); + stride = cursor->bits->width * 4; + if (cursor->bits->argb) + memcpy(pixmap->devPrivate.ptr, + cursor->bits->argb, cursor->bits->height * stride); + else + expand_source_and_mask(cursor, pixmap->devPrivate.ptr); + + wl_pointer_set_cursor(xwl_seat->wl_pointer, + xwl_seat->pointer_enter_serial, + xwl_seat->cursor, + xwl_seat->x_cursor->bits->xhot, + xwl_seat->x_cursor->bits->yhot); + wl_surface_attach(xwl_seat->cursor, + xwl_shm_pixmap_get_wl_buffer(pixmap), 0, 0); + wl_surface_damage(xwl_seat->cursor, 0, 0, + xwl_seat->x_cursor->bits->width, + xwl_seat->x_cursor->bits->height); + wl_surface_commit(xwl_seat->cursor); +} + +static void +xwl_set_cursor(DeviceIntPtr device, + ScreenPtr screen, CursorPtr cursor, int x, int y) +{ + struct xwl_seat *xwl_seat; + + xwl_seat = device->public.devicePrivate; + if (xwl_seat == NULL) + return; + + xwl_seat->x_cursor = cursor; + xwl_seat_set_cursor(xwl_seat); +} + +static void +xwl_move_cursor(DeviceIntPtr device, ScreenPtr screen, int x, int y) +{ +} + +static Bool +xwl_device_cursor_initialize(DeviceIntPtr device, ScreenPtr screen) +{ + return TRUE; +} + +static void +xwl_device_cursor_cleanup(DeviceIntPtr device, ScreenPtr screen) +{ +} + +static miPointerSpriteFuncRec xwl_pointer_sprite_funcs = { + xwl_realize_cursor, + xwl_unrealize_cursor, + xwl_set_cursor, + xwl_move_cursor, + xwl_device_cursor_initialize, + xwl_device_cursor_cleanup +}; + +static Bool +xwl_cursor_off_screen(ScreenPtr *ppScreen, int *x, int *y) +{ + return FALSE; +} + +static void +xwl_cross_screen(ScreenPtr pScreen, Bool entering) +{ +} + +static void +xwl_pointer_warp_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ +} + +static miPointerScreenFuncRec xwl_pointer_screen_funcs = { + xwl_cursor_off_screen, + xwl_cross_screen, + xwl_pointer_warp_cursor +}; + +Bool +xwl_screen_init_cursor(struct xwl_screen *xwl_screen) +{ + if (!dixRegisterPrivateKey(&xwl_cursor_private_key, PRIVATE_CURSOR_BITS, 0)) + return FALSE; + + return miPointerInitialize(xwl_screen->screen, + &xwl_pointer_sprite_funcs, + &xwl_pointer_screen_funcs, TRUE); +} diff --git a/xorg-server/hw/xwayland/xwayland-cvt.c b/xorg-server/hw/xwayland/xwayland-cvt.c new file mode 100644 index 000000000..35665597f --- /dev/null +++ b/xorg-server/hw/xwayland/xwayland-cvt.c @@ -0,0 +1,304 @@ +/* Copied from hw/xfree86/modes/xf86cvt.c into xwayland DDX and + * changed to generate an RRMode */ + +/* + * Copyright 2005-2006 Luc Verhaegen. + * + * 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. + */ + +/* + * The reason for having this function in a file of its own is + * so that ../utils/cvt/cvt can link to it, and that xf86CVTMode + * code is shared directly. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <string.h> +#include <randrstr.h> +#include "xwayland.h" + +/* + * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh. + * + * These calculations are stolen from the CVT calculation spreadsheet written + * by Graham Loveridge. He seems to be claiming no copyright and there seems to + * be no license attached to this. He apparently just wants to see his name + * mentioned. + * + * This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls + * + * Comments and structure corresponds to the comments and structure of the xls. + * This should ease importing of future changes to the standard (not very + * likely though). + * + * About margins; i'm sure that they are to be the bit between HDisplay and + * HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and + * VTotal, where the overscan colour is shown. FB seems to call _all_ blanking + * outside sync "margin" for some reason. Since we prefer seeing proper + * blanking instead of the overscan colour, and since the Crtc* values will + * probably get altered after us, we will disable margins altogether. With + * these calculations, Margins will plainly expand H/VDisplay, and we don't + * want that. -- libv + * + */ +RRModePtr +xwayland_cvt(int HDisplay, int VDisplay, float VRefresh, Bool Reduced, + Bool Interlaced) +{ + /* 1) top/bottom margin size (% of height) - default: 1.8 */ +#define CVT_MARGIN_PERCENTAGE 1.8 + + /* 2) character cell horizontal granularity (pixels) - default 8 */ +#define CVT_H_GRANULARITY 8 + + /* 4) Minimum vertical porch (lines) - default 3 */ +#define CVT_MIN_V_PORCH 3 + + /* 4) Minimum number of vertical back porch lines - default 6 */ +#define CVT_MIN_V_BPORCH 6 + + /* Pixel Clock step (kHz) */ +#define CVT_CLOCK_STEP 250 + + Bool Margins = FALSE; + float VFieldRate, HPeriod; + int HDisplayRnd, HMargin; + int VDisplayRnd, VMargin, VSync; + float Interlace; /* Please rename this */ + char name[128]; + xRRModeInfo modeinfo; + + memset(&modeinfo, 0, sizeof modeinfo); + + /* CVT default is 60.0Hz */ + if (!VRefresh) + VRefresh = 60.0; + + /* 1. Required field rate */ + if (Interlaced) + VFieldRate = VRefresh * 2; + else + VFieldRate = VRefresh; + + /* 2. Horizontal pixels */ + HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY); + + /* 3. Determine left and right borders */ + if (Margins) { + /* right margin is actually exactly the same as left */ + HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0); + HMargin -= HMargin % CVT_H_GRANULARITY; + } + else + HMargin = 0; + + /* 4. Find total active pixels */ + modeinfo.width = HDisplayRnd + 2 * HMargin; + + /* 5. Find number of lines per field */ + if (Interlaced) + VDisplayRnd = VDisplay / 2; + else + VDisplayRnd = VDisplay; + + /* 6. Find top and bottom margins */ + /* nope. */ + if (Margins) + /* top and bottom margins are equal again. */ + VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0); + else + VMargin = 0; + + modeinfo.height = VDisplay + 2 * VMargin; + + /* 7. Interlace */ + if (Interlaced) + Interlace = 0.5; + else + Interlace = 0.0; + + /* Determine VSync Width from aspect ratio */ + if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay)) + VSync = 4; + else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay)) + VSync = 5; + else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay)) + VSync = 6; + else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay)) + VSync = 7; + else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay)) + VSync = 7; + else /* Custom */ + VSync = 10; + + if (!Reduced) { /* simplified GTF calculation */ + + /* 4) Minimum time of vertical sync + back porch interval (µs) + * default 550.0 */ +#define CVT_MIN_VSYNC_BP 550.0 + + /* 3) Nominal HSync width (% of line period) - default 8 */ +#define CVT_HSYNC_PERCENTAGE 8 + + float HBlankPercentage; + int VSyncAndBackPorch, VBackPorch; + int HBlank; + + /* 8. Estimated Horizontal period */ + HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) / + (VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace); + + /* 9. Find number of lines in sync + backporch */ + if (((int) (CVT_MIN_VSYNC_BP / HPeriod) + 1) < + (VSync + CVT_MIN_V_PORCH)) + VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH; + else + VSyncAndBackPorch = (int) (CVT_MIN_VSYNC_BP / HPeriod) + 1; + + /* 10. Find number of lines in back porch */ + VBackPorch = VSyncAndBackPorch - VSync; + (void) VBackPorch; + + /* 11. Find total number of lines in vertical field */ + modeinfo.vTotal = + VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace + + CVT_MIN_V_PORCH; + + /* 5) Definition of Horizontal blanking time limitation */ + /* Gradient (%/kHz) - default 600 */ +#define CVT_M_FACTOR 600 + + /* Offset (%) - default 40 */ +#define CVT_C_FACTOR 40 + + /* Blanking time scaling factor - default 128 */ +#define CVT_K_FACTOR 128 + + /* Scaling factor weighting - default 20 */ +#define CVT_J_FACTOR 20 + +#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256 +#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \ + CVT_J_FACTOR + + /* 12. Find ideal blanking duty cycle from formula */ + HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod / 1000.0; + + /* 13. Blanking time */ + if (HBlankPercentage < 20) + HBlankPercentage = 20; + + HBlank = modeinfo.width * HBlankPercentage / (100.0 - HBlankPercentage); + HBlank -= HBlank % (2 * CVT_H_GRANULARITY); + + /* 14. Find total number of pixels in a line. */ + modeinfo.hTotal = modeinfo.width + HBlank; + + /* Fill in HSync values */ + modeinfo.hSyncEnd = modeinfo.width + HBlank / 2; + + modeinfo.hSyncStart = modeinfo.hSyncEnd - + (modeinfo.hTotal * CVT_HSYNC_PERCENTAGE) / 100; + modeinfo.hSyncStart += CVT_H_GRANULARITY - + modeinfo.hSyncStart % CVT_H_GRANULARITY; + + /* Fill in VSync values */ + modeinfo.vSyncStart = modeinfo.height + CVT_MIN_V_PORCH; + modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync; + + } + else { /* Reduced blanking */ + /* Minimum vertical blanking interval time (µs) - default 460 */ +#define CVT_RB_MIN_VBLANK 460.0 + + /* Fixed number of clocks for horizontal sync */ +#define CVT_RB_H_SYNC 32.0 + + /* Fixed number of clocks for horizontal blanking */ +#define CVT_RB_H_BLANK 160.0 + + /* Fixed number of lines for vertical front porch - default 3 */ +#define CVT_RB_VFPORCH 3 + + int VBILines; + + /* 8. Estimate Horizontal period. */ + HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) / + (VDisplayRnd + 2 * VMargin); + + /* 9. Find number of lines in vertical blanking */ + VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1; + + /* 10. Check if vertical blanking is sufficient */ + if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH)) + VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH; + + /* 11. Find total number of lines in vertical field */ + modeinfo.vTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines; + + /* 12. Find total number of pixels in a line */ + modeinfo.hTotal = modeinfo.width + CVT_RB_H_BLANK; + + /* Fill in HSync values */ + modeinfo.hSyncEnd = modeinfo.width + CVT_RB_H_BLANK / 2; + modeinfo.hSyncStart = modeinfo.hSyncEnd - CVT_RB_H_SYNC; + + /* Fill in VSync values */ + modeinfo.vSyncStart = modeinfo.height + CVT_RB_VFPORCH; + modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync; + } + + /* 15/13. Find pixel clock frequency (kHz for xf86) */ + modeinfo.dotClock = modeinfo.hTotal * 1000.0 / HPeriod; + modeinfo.dotClock -= modeinfo.dotClock % CVT_CLOCK_STEP; + modeinfo.dotClock *= 1000.0; +#if 0 + /* 16/14. Find actual Horizontal Frequency (kHz) */ + modeinfo.hSync = ((float) modeinfo.dotClock) / ((float) modeinfo.hTotal); +#endif + +#if 0 + /* 17/15. Find actual Field rate */ + modeinfo.vRefresh = (1000.0 * ((float) modeinfo.dotClock)) / + ((float) (modeinfo.hTotal * modeinfo.vTotal)); +#endif + + /* 18/16. Find actual vertical frame frequency */ + /* ignore - just set the mode flag for interlaced */ + if (Interlaced) + modeinfo.vTotal *= 2; + + if (Reduced) + modeinfo.modeFlags |= RR_HSyncPositive | RR_VSyncNegative; + else + modeinfo.modeFlags |= RR_HSyncNegative | RR_VSyncPositive; + + if (Interlaced) + modeinfo.modeFlags |= RR_Interlace; + + snprintf(name, sizeof name, "%dx%d@%.1fHz", + modeinfo.width, modeinfo.height, VRefresh); + modeinfo.nameLength = strlen(name); + + return RRModeGet(&modeinfo, name); +} diff --git a/xorg-server/hw/xwayland/xwayland-input.c b/xorg-server/hw/xwayland/xwayland-input.c new file mode 100644 index 000000000..990cb82d8 --- /dev/null +++ b/xorg-server/hw/xwayland/xwayland-input.c @@ -0,0 +1,666 @@ +/* + * Copyright © 2014 Intel Corporation + * Copyright © 2008 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of the + * copyright holders not be used in advertising or publicity + * pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "xwayland.h" + +#include <linux/input.h> + +#include <sys/mman.h> +#include <xkbsrv.h> +#include <xserver-properties.h> +#include <inpututils.h> + +static void +xwl_pointer_control(DeviceIntPtr device, PtrCtrl *ctrl) +{ + /* Nothing to do, dix handles all settings */ +} + +static int +xwl_pointer_proc(DeviceIntPtr device, int what) +{ +#define NBUTTONS 10 +#define NAXES 2 + BYTE map[NBUTTONS + 1]; + int i = 0; + Atom btn_labels[NBUTTONS] = { 0 }; + Atom axes_labels[NAXES] = { 0 }; + + switch (what) { + case DEVICE_INIT: + device->public.on = FALSE; + + for (i = 1; i <= NBUTTONS; i++) + map[i] = i; + + btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); + btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); + btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); + btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); + btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); + btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); + btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); + /* don't know about the rest */ + + axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X); + axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y); + + if (!InitValuatorClassDeviceStruct(device, 2, btn_labels, + GetMotionHistorySize(), Absolute)) + return BadValue; + + /* Valuators */ + InitValuatorAxisStruct(device, 0, axes_labels[0], + 0, 0xFFFF, 10000, 0, 10000, Absolute); + InitValuatorAxisStruct(device, 1, axes_labels[1], + 0, 0xFFFF, 10000, 0, 10000, Absolute); + + if (!InitPtrFeedbackClassDeviceStruct(device, xwl_pointer_control)) + return BadValue; + + if (!InitButtonClassDeviceStruct(device, 3, btn_labels, map)) + return BadValue; + + return Success; + + case DEVICE_ON: + device->public.on = TRUE; + return Success; + + case DEVICE_OFF: + case DEVICE_CLOSE: + device->public.on = FALSE; + return Success; + } + + return BadMatch; + +#undef NBUTTONS +#undef NAXES +} + +static void +xwl_keyboard_control(DeviceIntPtr device, KeybdCtrl *ctrl) +{ +} + +static int +xwl_keyboard_proc(DeviceIntPtr device, int what) +{ + struct xwl_seat *xwl_seat = device->public.devicePrivate; + int len; + + switch (what) { + case DEVICE_INIT: + device->public.on = FALSE; + if (xwl_seat->keymap) + len = strnlen(xwl_seat->keymap, xwl_seat->keymap_size); + else + len = 0; + if (!InitKeyboardDeviceStructFromString(device, xwl_seat->keymap, + len, + NULL, xwl_keyboard_control)) + return BadValue; + + return Success; + case DEVICE_ON: + device->public.on = TRUE; + return Success; + + case DEVICE_OFF: + case DEVICE_CLOSE: + device->public.on = FALSE; + return Success; + } + + return BadMatch; +} + +static void +pointer_handle_enter(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface, + wl_fixed_t sx_w, wl_fixed_t sy_w) +{ + struct xwl_seat *xwl_seat = data; + DeviceIntPtr dev = xwl_seat->pointer; + int i; + int sx = wl_fixed_to_int(sx_w); + int sy = wl_fixed_to_int(sy_w); + ScreenPtr pScreen = xwl_seat->xwl_screen->screen; + ValuatorMask mask; + + xwl_seat->xwl_screen->serial = serial; + xwl_seat->pointer_enter_serial = serial; + + xwl_seat->focus_window = wl_surface_get_user_data(surface); + + (*pScreen->SetCursorPosition) (dev, pScreen, sx, sy, TRUE); + CheckMotion(NULL, GetMaster(dev, MASTER_POINTER)); + + /* Ideally, X clients shouldn't see these button releases. When + * the pointer leaves a window with buttons down, it means that + * the wayland compositor has grabbed the pointer. The button + * release event is consumed by whatever grab in the compositor + * and won't be sent to clients (the X server is a client). + * However, we need to reset X's idea of which buttons are up and + * down, and they're all up (by definition) when the pointer + * enters a window. We should figure out a way to swallow these + * events, perhaps using an X grab whenever the pointer is not in + * any X window, but for now just send the events. */ + valuator_mask_zero(&mask); + for (i = 0; i < dev->button->numButtons; i++) + if (BitIsOn(dev->button->down, i)) + QueuePointerEvents(xwl_seat->pointer, ButtonRelease, i, 0, &mask); +} + +static void +pointer_handle_leave(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface) +{ + struct xwl_seat *xwl_seat = data; + DeviceIntPtr dev = xwl_seat->pointer; + + xwl_seat->xwl_screen->serial = serial; + + xwl_seat->focus_window = NULL; + CheckMotion(NULL, GetMaster(dev, MASTER_POINTER)); +} + +static void +pointer_handle_motion(void *data, struct wl_pointer *pointer, + uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) +{ + struct xwl_seat *xwl_seat = data; + int32_t dx, dy; + int sx = wl_fixed_to_int(sx_w); + int sy = wl_fixed_to_int(sy_w); + ValuatorMask mask; + + if (!xwl_seat->focus_window) + return; + + dx = xwl_seat->focus_window->window->drawable.x; + dy = xwl_seat->focus_window->window->drawable.y; + + valuator_mask_zero(&mask); + valuator_mask_set(&mask, 0, dx + sx); + valuator_mask_set(&mask, 1, dy + sy); + + QueuePointerEvents(xwl_seat->pointer, MotionNotify, 0, + POINTER_ABSOLUTE | POINTER_SCREEN, &mask); +} + +static void +pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, + uint32_t time, uint32_t button, uint32_t state) +{ + struct xwl_seat *xwl_seat = data; + int index; + ValuatorMask mask; + + xwl_seat->xwl_screen->serial = serial; + + switch (button) { + case BTN_MIDDLE: + index = 2; + break; + case BTN_RIGHT: + index = 3; + break; + default: + index = button - BTN_LEFT + 1; + break; + } + + valuator_mask_zero(&mask); + QueuePointerEvents(xwl_seat->pointer, + state ? ButtonPress : ButtonRelease, index, 0, &mask); +} + +static void +pointer_handle_axis(void *data, struct wl_pointer *pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ + struct xwl_seat *xwl_seat = data; + int index, count; + int i, val; + const int divisor = 10; + ValuatorMask mask; + + if (time - xwl_seat->scroll_time > 2000) { + xwl_seat->vertical_scroll = 0; + xwl_seat->horizontal_scroll = 0; + } + xwl_seat->scroll_time = time; + + /* FIXME: Need to do proper smooth scrolling here! */ + switch (axis) { + case WL_POINTER_AXIS_VERTICAL_SCROLL: + xwl_seat->vertical_scroll += value / divisor; + val = wl_fixed_to_int(xwl_seat->vertical_scroll); + xwl_seat->vertical_scroll -= wl_fixed_from_int(val); + + if (val <= -1) + index = 4; + else if (val >= 1) + index = 5; + else + return; + break; + case WL_POINTER_AXIS_HORIZONTAL_SCROLL: + xwl_seat->horizontal_scroll += value / divisor; + val = wl_fixed_to_int(xwl_seat->horizontal_scroll); + xwl_seat->horizontal_scroll -= wl_fixed_from_int(val); + + if (val <= -1) + index = 6; + else if (val >= 1) + index = 7; + else + return; + break; + default: + return; + } + + valuator_mask_zero(&mask); + + count = abs(val); + for (i = 0; i < count; i++) { + QueuePointerEvents(xwl_seat->pointer, ButtonPress, index, 0, &mask); + QueuePointerEvents(xwl_seat->pointer, ButtonRelease, index, 0, &mask); + } +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + +static void +keyboard_handle_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, + uint32_t time, uint32_t key, uint32_t state) +{ + struct xwl_seat *xwl_seat = data; + uint32_t *k, *end; + ValuatorMask mask; + + xwl_seat->xwl_screen->serial = serial; + + end = (uint32_t *) ((char *) xwl_seat->keys.data + xwl_seat->keys.size); + for (k = xwl_seat->keys.data; k < end; k++) { + if (*k == key) + *k = *--end; + } + xwl_seat->keys.size = (char *) end - (char *) xwl_seat->keys.data; + if (state) { + k = wl_array_add(&xwl_seat->keys, sizeof *k); + *k = key; + } + + valuator_mask_zero(&mask); + QueueKeyboardEvents(xwl_seat->keyboard, + state ? KeyPress : KeyRelease, key + 8, &mask); +} + +static void +keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, + uint32_t format, int fd, uint32_t size) +{ + struct xwl_seat *xwl_seat = data; + DeviceIntPtr master; + XkbDescPtr xkb; + XkbChangesRec changes = { 0 }; + + if (xwl_seat->keymap) + munmap(xwl_seat->keymap, xwl_seat->keymap_size); + + xwl_seat->keymap_size = size; + xwl_seat->keymap = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (xwl_seat->keymap == MAP_FAILED) { + xwl_seat->keymap_size = 0; + xwl_seat->keymap = NULL; + goto out; + } + + xkb = XkbCompileKeymapFromString(xwl_seat->keyboard, xwl_seat->keymap, + strnlen(xwl_seat->keymap, + xwl_seat->keymap_size)); + if (!xkb) + goto out; + + XkbUpdateDescActions(xkb, xkb->min_key_code, XkbNumKeys(xkb), &changes); + + if (xwl_seat->keyboard->key) + /* Keep the current controls */ + XkbCopyControls(xkb, xwl_seat->keyboard->key->xkbInfo->desc); + + XkbDeviceApplyKeymap(xwl_seat->keyboard, xkb); + + master = GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD); + if (master && master->lastSlave == xwl_seat->keyboard) + XkbDeviceApplyKeymap(master, xkb); + + XkbFreeKeyboard(xkb, XkbAllComponentsMask, TRUE); + + out: + close(fd); +} + +static void +keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, + uint32_t serial, + struct wl_surface *surface, struct wl_array *keys) +{ + struct xwl_seat *xwl_seat = data; + ValuatorMask mask; + uint32_t *k; + + xwl_seat->xwl_screen->serial = serial; + xwl_seat->keyboard_focus = surface; + + wl_array_copy(&xwl_seat->keys, keys); + valuator_mask_zero(&mask); + wl_array_for_each(k, &xwl_seat->keys) + QueueKeyboardEvents(xwl_seat->keyboard, KeyPress, *k + 8, &mask); +} + +static void +keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, + uint32_t serial, struct wl_surface *surface) +{ + struct xwl_seat *xwl_seat = data; + ValuatorMask mask; + uint32_t *k; + + xwl_seat->xwl_screen->serial = serial; + + valuator_mask_zero(&mask); + wl_array_for_each(k, &xwl_seat->keys) + QueueKeyboardEvents(xwl_seat->keyboard, KeyRelease, *k + 8, &mask); + + xwl_seat->keyboard_focus = NULL; +} + +static void +keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, + uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, + uint32_t group) +{ + struct xwl_seat *xwl_seat = data; + DeviceIntPtr dev; + XkbStateRec old_state, *new_state; + xkbStateNotify sn; + CARD16 changed; + + /* We don't need any of this while we have keyboard focus since + the regular key event processing already takes care of setting + our internal state correctly. */ + if (xwl_seat->keyboard_focus) + return; + + for (dev = inputInfo.devices; dev; dev = dev->next) { + if (dev != xwl_seat->keyboard && + dev != GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD)) + continue; + + old_state = dev->key->xkbInfo->state; + new_state = &dev->key->xkbInfo->state; + + new_state->locked_group = group & XkbAllGroupsMask; + new_state->locked_mods = mods_locked & XkbAllModifiersMask; + XkbLatchModifiers(dev, XkbAllModifiersMask, + mods_latched & XkbAllModifiersMask); + + XkbComputeDerivedState(dev->key->xkbInfo); + + changed = XkbStateChangedFlags(&old_state, new_state); + if (!changed) + continue; + + sn.keycode = 0; + sn.eventType = 0; + sn.requestMajor = XkbReqCode; + sn.requestMinor = X_kbLatchLockState; /* close enough */ + sn.changed = changed; + XkbSendStateNotify(dev, &sn); + } +} + +static const struct wl_keyboard_listener keyboard_listener = { + keyboard_handle_keymap, + keyboard_handle_enter, + keyboard_handle_leave, + keyboard_handle_key, + keyboard_handle_modifiers, +}; + +static DeviceIntPtr +add_device(struct xwl_seat *xwl_seat, + const char *driver, DeviceProc device_proc) +{ + DeviceIntPtr dev = NULL; + static Atom type_atom; + char name[32]; + + dev = AddInputDevice(serverClient, device_proc, TRUE); + if (dev == NULL) + return NULL; + + if (type_atom == None) + type_atom = MakeAtom(driver, strlen(driver), TRUE); + snprintf(name, sizeof name, "%s:%d", driver, xwl_seat->id); + AssignTypeAndName(dev, type_atom, name); + dev->public.devicePrivate = xwl_seat; + dev->type = SLAVE; + dev->spriteInfo->spriteOwner = FALSE; + + return dev; +} + +static void +seat_handle_capabilities(void *data, struct wl_seat *seat, + enum wl_seat_capability caps) +{ + struct xwl_seat *xwl_seat = data; + + if (caps & WL_SEAT_CAPABILITY_POINTER && xwl_seat->pointer == NULL) { + xwl_seat->wl_pointer = wl_seat_get_pointer(seat); + wl_pointer_add_listener(xwl_seat->wl_pointer, + &pointer_listener, xwl_seat); + xwl_seat_set_cursor(xwl_seat); + xwl_seat->pointer = + add_device(xwl_seat, "xwayland-pointer", xwl_pointer_proc); + } + else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && xwl_seat->pointer) { + wl_pointer_release(xwl_seat->wl_pointer); + RemoveDevice(xwl_seat->pointer, FALSE); + xwl_seat->pointer = NULL; + } + + if (caps & WL_SEAT_CAPABILITY_KEYBOARD && xwl_seat->keyboard == NULL) { + xwl_seat->wl_keyboard = wl_seat_get_keyboard(seat); + wl_keyboard_add_listener(xwl_seat->wl_keyboard, + &keyboard_listener, xwl_seat); + xwl_seat->keyboard = + add_device(xwl_seat, "xwayland-keyboard", xwl_keyboard_proc); + } + else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && xwl_seat->keyboard) { + wl_keyboard_release(xwl_seat->wl_keyboard); + RemoveDevice(xwl_seat->keyboard, FALSE); + xwl_seat->keyboard = NULL; + } + + xwl_seat->xwl_screen->expecting_event--; + /* FIXME: Touch ... */ +} + +static void +seat_handle_name(void *data, struct wl_seat *seat, + const char *name) +{ + +} + +static const struct wl_seat_listener seat_listener = { + seat_handle_capabilities, + seat_handle_name +}; + +static void +create_input_device(struct xwl_screen *xwl_screen, uint32_t id) +{ + struct xwl_seat *xwl_seat; + + xwl_seat = calloc(sizeof *xwl_seat, 1); + if (xwl_seat == NULL) { + ErrorF("create_input ENOMEM"); + return; + } + + xwl_seat->xwl_screen = xwl_screen; + xorg_list_add(&xwl_seat->link, &xwl_screen->seat_list); + + xwl_seat->seat = + wl_registry_bind(xwl_screen->registry, id, &wl_seat_interface, 3); + xwl_seat->id = id; + + xwl_seat->cursor = wl_compositor_create_surface(xwl_screen->compositor); + wl_seat_add_listener(xwl_seat->seat, &seat_listener, xwl_seat); + wl_array_init(&xwl_seat->keys); +} + +void +xwl_seat_destroy(struct xwl_seat *xwl_seat) +{ + RemoveDevice(xwl_seat->pointer, FALSE); + RemoveDevice(xwl_seat->keyboard, FALSE); + wl_seat_destroy(xwl_seat->seat); + wl_surface_destroy(xwl_seat->cursor); + wl_array_release(&xwl_seat->keys); + free(xwl_seat); +} + +static void +input_handler(void *data, struct wl_registry *registry, uint32_t id, + const char *interface, uint32_t version) +{ + struct xwl_screen *xwl_screen = data; + + if (strcmp(interface, "wl_seat") == 0 && version >= 3) { + create_input_device(xwl_screen, id); + xwl_screen->expecting_event++; + } +} + +static void +global_remove(void *data, struct wl_registry *registry, uint32_t name) +{ +} + +static const struct wl_registry_listener input_listener = { + input_handler, + global_remove, +}; + +Bool +LegalModifier(unsigned int key, DeviceIntPtr pDev) +{ + return TRUE; +} + +void +ProcessInputEvents(void) +{ + mieqProcessInputEvents(); +} + +void +DDXRingBell(int volume, int pitch, int duration) +{ +} + +static WindowPtr +xwl_xy_to_window(ScreenPtr screen, SpritePtr sprite, int x, int y) +{ + struct xwl_seat *xwl_seat = NULL; + DeviceIntPtr device; + + for (device = inputInfo.devices; device; device = device->next) { + if (device->deviceProc == xwl_pointer_proc && + device->spriteInfo->sprite == sprite) { + xwl_seat = device->public.devicePrivate; + break; + } + } + + if (xwl_seat == NULL) { + /* XTEST device */ + sprite->spriteTraceGood = 1; + return sprite->spriteTrace[0]; + } + + if (xwl_seat->focus_window) { + sprite->spriteTraceGood = 2; + sprite->spriteTrace[1] = xwl_seat->focus_window->window; + return miSpriteTrace(sprite, x, y); + } + else { + sprite->spriteTraceGood = 1; + return sprite->spriteTrace[0]; + } +} + +void +InitInput(int argc, char *argv[]) +{ + ScreenPtr pScreen = screenInfo.screens[0]; + struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); + + mieqInit(); + + xwl_screen->input_registry = wl_display_get_registry(xwl_screen->display); + wl_registry_add_listener(xwl_screen->input_registry, &input_listener, + xwl_screen); + + xwl_screen->XYToWindow = pScreen->XYToWindow; + pScreen->XYToWindow = xwl_xy_to_window; + + xwl_screen->expecting_event = 0; + wl_display_roundtrip(xwl_screen->display); + while (xwl_screen->expecting_event) + wl_display_roundtrip(xwl_screen->display); +} + +void +CloseInput(void) +{ + mieqFini(); +} diff --git a/xorg-server/hw/xwayland/xwayland-output.c b/xorg-server/hw/xwayland/xwayland-output.c new file mode 100644 index 000000000..778914c61 --- /dev/null +++ b/xorg-server/hw/xwayland/xwayland-output.c @@ -0,0 +1,226 @@ +/* + * Copyright © 2011-2014 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of the + * copyright holders not be used in advertising or publicity + * pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "xwayland.h" +#include <randrstr.h> + +static Rotation +wl_transform_to_xrandr(enum wl_output_transform transform) +{ + switch (transform) { + default: + case WL_OUTPUT_TRANSFORM_NORMAL: + return RR_Rotate_0; + case WL_OUTPUT_TRANSFORM_90: + return RR_Rotate_90; + case WL_OUTPUT_TRANSFORM_180: + return RR_Rotate_180; + case WL_OUTPUT_TRANSFORM_270: + return RR_Rotate_270; + case WL_OUTPUT_TRANSFORM_FLIPPED: + return RR_Reflect_X | RR_Rotate_0; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + return RR_Reflect_X | RR_Rotate_90; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + return RR_Reflect_X | RR_Rotate_180; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + return RR_Reflect_X | RR_Rotate_270; + } +} + +static int +wl_subpixel_to_xrandr(int subpixel) +{ + switch (subpixel) { + default: + case WL_OUTPUT_SUBPIXEL_UNKNOWN: + return SubPixelUnknown; + case WL_OUTPUT_SUBPIXEL_NONE: + return SubPixelNone; + case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB: + return SubPixelHorizontalRGB; + case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR: + return SubPixelHorizontalBGR; + case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB: + return SubPixelVerticalRGB; + case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR: + return SubPixelVerticalBGR; + } +} + +static void +output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y, + int physical_width, int physical_height, int subpixel, + const char *make, const char *model, int transform) +{ + struct xwl_output *xwl_output = data; + + RROutputSetPhysicalSize(xwl_output->randr_output, + physical_width, physical_height); + RROutputSetSubpixelOrder(xwl_output->randr_output, + wl_subpixel_to_xrandr(subpixel)); + xwl_output->x = x; + xwl_output->y = y; + + xwl_output->rotation = wl_transform_to_xrandr(transform); +} + +static void +output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags, + int width, int height, int refresh) +{ + struct xwl_output *xwl_output = data; + RRModePtr randr_mode; + + if (!(flags & WL_OUTPUT_MODE_CURRENT)) + return; + + xwl_output->width = width; + xwl_output->height = height; + + randr_mode = xwayland_cvt(width, height, refresh / 1000.0, 0, 0); + + RROutputSetModes(xwl_output->randr_output, &randr_mode, 1, 1); + + RRCrtcNotify(xwl_output->randr_crtc, randr_mode, + xwl_output->x, xwl_output->y, + xwl_output->rotation, NULL, 1, &xwl_output->randr_output); +} + +static void +output_handle_done(void *data, struct wl_output *wl_output) +{ + struct xwl_output *xwl_output = data; + struct xwl_screen *xwl_screen = xwl_output->xwl_screen; + int width, height; + + xorg_list_append(&xwl_output->link, &xwl_screen->output_list); + + width = 0; + height = 0; + xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) { + if (width < xwl_output->x + xwl_output->width) + width = xwl_output->x + xwl_output->width; + if (height < xwl_output->y + xwl_output->height) + height = xwl_output->y + xwl_output->height; + } + + xwl_screen->width = width; + xwl_screen->height = height; + RRScreenSizeNotify(xwl_screen->screen); + + xwl_screen->expecting_event--; +} + +static void +output_handle_scale(void *data, struct wl_output *wl_output, int32_t factor) +{ +} + +static const struct wl_output_listener output_listener = { + output_handle_geometry, + output_handle_mode, + output_handle_done, + output_handle_scale +}; + +struct xwl_output * +xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id) +{ + struct xwl_output *xwl_output; + static int serial; + char name[256]; + + xwl_output = calloc(sizeof *xwl_output, 1); + if (xwl_output == NULL) { + ErrorF("create_output ENOMEM"); + return NULL; + } + + xwl_output->output = wl_registry_bind(xwl_screen->registry, id, + &wl_output_interface, 2); + wl_output_add_listener(xwl_output->output, &output_listener, xwl_output); + + if (snprintf(name, sizeof name, "XWAYLAND%d", serial++) < 0) { + ErrorF("create_output ENOMEM"); + free(xwl_output); + return NULL; + } + + xwl_output->xwl_screen = xwl_screen; + xwl_output->randr_crtc = RRCrtcCreate(xwl_screen->screen, xwl_output); + xwl_output->randr_output = RROutputCreate(xwl_screen->screen, name, + strlen(name), xwl_output); + RRCrtcGammaSetSize(xwl_output->randr_crtc, 256); + RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1); + RROutputSetConnection(xwl_output->randr_output, RR_Connected); + + return xwl_output; +} + +void +xwl_output_destroy(struct xwl_output *xwl_output) +{ + wl_output_destroy(xwl_output->output); + RRCrtcDestroy(xwl_output->randr_crtc); + RROutputDestroy(xwl_output->randr_output); + free(xwl_output); +} + +static Bool +xwl_randr_get_info(ScreenPtr pScreen, Rotation * rotations) +{ + *rotations = 0; + + return TRUE; +} + +static Bool +xwl_randr_set_config(ScreenPtr pScreen, + Rotation rotation, int rate, RRScreenSizePtr pSize) +{ + return FALSE; +} + +Bool +xwl_screen_init_output(struct xwl_screen *xwl_screen) +{ + rrScrPrivPtr rp; + + if (!RRScreenInit(xwl_screen->screen)) + return FALSE; + + RRScreenSetSizeRange(xwl_screen->screen, 320, 200, 8192, 8192); + + rp = rrGetScrPriv(xwl_screen->screen); + rp->rrGetInfo = xwl_randr_get_info; + rp->rrSetConfig = xwl_randr_set_config; + + return TRUE; +} diff --git a/xorg-server/hw/xwayland/xwayland-shm.c b/xorg-server/hw/xwayland/xwayland-shm.c new file mode 100644 index 000000000..2d0ce3eb6 --- /dev/null +++ b/xorg-server/hw/xwayland/xwayland-shm.c @@ -0,0 +1,292 @@ +/* + * Copyright © 2014 Intel Corporation + * Copyright © 2012 Collabora, Ltd. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of the + * copyright holders not be used in advertising or publicity + * pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "xwayland.h" + +#include <sys/mman.h> +#include <sys/types.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> + +struct xwl_pixmap { + struct wl_buffer *buffer; + int fd; + void *data; + size_t size; +}; + +#ifndef HAVE_MKOSTEMP +static int +set_cloexec_or_close(int fd) +{ + long flags; + + if (fd == -1) + return -1; + + flags = fcntl(fd, F_GETFD); + if (flags == -1) + goto err; + + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) + goto err; + + return fd; + + err: + close(fd); + return -1; +} +#endif + +static int +create_tmpfile_cloexec(char *tmpname) +{ + int fd; + +#ifdef HAVE_MKOSTEMP + fd = mkostemp(tmpname, O_CLOEXEC); + if (fd >= 0) + unlink(tmpname); +#else + fd = mkstemp(tmpname); + if (fd >= 0) { + fd = set_cloexec_or_close(fd); + unlink(tmpname); + } +#endif + + return fd; +} + +/* + * Create a new, unique, anonymous file of the given size, and + * return the file descriptor for it. The file descriptor is set + * CLOEXEC. The file is immediately suitable for mmap()'ing + * the given size at offset zero. + * + * The file should not have a permanent backing store like a disk, + * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. + * + * The file name is deleted from the file system. + * + * The file is suitable for buffer sharing between processes by + * transmitting the file descriptor over Unix sockets using the + * SCM_RIGHTS methods. + * + * If the C library implements posix_fallocate(), it is used to + * guarantee that disk space is available for the file at the + * given size. If disk space is insufficent, errno is set to ENOSPC. + * If posix_fallocate() is not supported, program may receive + * SIGBUS on accessing mmap()'ed file contents instead. + */ +static int +os_create_anonymous_file(off_t size) +{ + static const char template[] = "/weston-shared-XXXXXX"; + const char *path; + char *name; + int fd; + int ret; + + path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + errno = ENOENT; + return -1; + } + + name = malloc(strlen(path) + sizeof(template)); + if (!name) + return -1; + + strcpy(name, path); + strcat(name, template); + + fd = create_tmpfile_cloexec(name); + + free(name); + + if (fd < 0) + return -1; + +#ifdef HAVE_POSIX_FALLOCATE + ret = posix_fallocate(fd, 0, size); + if (ret != 0) { + close(fd); + errno = ret; + return -1; + } +#else + ret = ftruncate(fd, size); + if (ret < 0) { + close(fd); + return -1; + } +#endif + + return fd; +} + +static uint32_t +shm_format_for_depth(int depth) +{ + switch (depth) { + case 32: + return WL_SHM_FORMAT_ARGB8888; + case 24: + default: + return WL_SHM_FORMAT_XRGB8888; +#ifdef WL_SHM_FORMAT_RGB565 + case 16: + /* XXX: Check run-time protocol version too */ + return WL_SHM_FORMAT_RGB565; +#endif + } +} + +PixmapPtr +xwl_shm_create_pixmap(ScreenPtr screen, + int width, int height, int depth, unsigned int hint) +{ + PixmapPtr pixmap; + struct xwl_pixmap *xwl_pixmap; + size_t size, stride; + + if (hint == CREATE_PIXMAP_USAGE_GLYPH_PICTURE || + (width == 0 && height == 0) || depth < 15) + return fbCreatePixmap(screen, width, height, depth, hint); + + pixmap = fbCreatePixmap(screen, 0, 0, depth, hint); + if (!pixmap) + return NULL; + + xwl_pixmap = malloc(sizeof *xwl_pixmap); + if (xwl_pixmap == NULL) + goto err_destroy_pixmap; + + stride = PixmapBytePad(width, depth); + size = stride * height; + xwl_pixmap->buffer = NULL; + xwl_pixmap->size = size; + xwl_pixmap->fd = os_create_anonymous_file(size); + if (xwl_pixmap->fd < 0) + goto err_free_xwl_pixmap; + + xwl_pixmap->data = mmap(NULL, size, PROT_READ | PROT_WRITE, + MAP_SHARED, xwl_pixmap->fd, 0); + if (xwl_pixmap->data == MAP_FAILED) + goto err_close_fd; + + if (!(*screen->ModifyPixmapHeader) (pixmap, width, height, depth, + BitsPerPixel(depth), + stride, xwl_pixmap->data)) + goto err_munmap; + + xwl_pixmap_set_private(pixmap, xwl_pixmap); + + return pixmap; + + err_munmap: + munmap(xwl_pixmap->data, size); + err_close_fd: + close(xwl_pixmap->fd); + err_free_xwl_pixmap: + free(xwl_pixmap); + err_destroy_pixmap: + fbDestroyPixmap(pixmap); + + return NULL; +} + +Bool +xwl_shm_destroy_pixmap(PixmapPtr pixmap) +{ + struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap); + + if (xwl_pixmap && pixmap->refcnt == 1) { + if (xwl_pixmap->buffer) + wl_buffer_destroy(xwl_pixmap->buffer); + munmap(xwl_pixmap->data, xwl_pixmap->size); + close(xwl_pixmap->fd); + free(xwl_pixmap); + } + + return fbDestroyPixmap(pixmap); +} + +struct wl_buffer * +xwl_shm_pixmap_get_wl_buffer(PixmapPtr pixmap) +{ + struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen); + struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap); + struct wl_shm_pool *pool; + uint32_t format; + + if (xwl_pixmap->buffer) + return xwl_pixmap->buffer; + + pool = wl_shm_create_pool(xwl_screen->shm, + xwl_pixmap->fd, xwl_pixmap->size); + + format = shm_format_for_depth(pixmap->drawable.depth); + xwl_pixmap->buffer = wl_shm_pool_create_buffer(pool, 0, + pixmap->drawable.width, + pixmap->drawable.height, + pixmap->devKind, format); + + wl_shm_pool_destroy(pool); + + return xwl_pixmap->buffer; +} + +Bool +xwl_shm_create_screen_resources(ScreenPtr screen) +{ + struct xwl_screen *xwl_screen = xwl_screen_get(screen); + int ret; + + screen->CreateScreenResources = xwl_screen->CreateScreenResources; + ret = (*screen->CreateScreenResources) (screen); + xwl_screen->CreateScreenResources = screen->CreateScreenResources; + screen->CreateScreenResources = xwl_shm_create_screen_resources; + + if (!ret) + return ret; + + if (xwl_screen->rootless) + screen->devPrivate = + fbCreatePixmap(screen, 0, 0, screen->rootDepth, 0); + else + screen->devPrivate = + xwl_shm_create_pixmap(screen, screen->width, screen->height, + screen->rootDepth, + CREATE_PIXMAP_USAGE_BACKING_PIXMAP); + + return screen->devPrivate != NULL; +} diff --git a/xorg-server/hw/xwayland/xwayland.c b/xorg-server/hw/xwayland/xwayland.c new file mode 100644 index 000000000..c2c6481af --- /dev/null +++ b/xorg-server/hw/xwayland/xwayland.c @@ -0,0 +1,652 @@ +/* + * Copyright © 2011-2014 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of the + * copyright holders not be used in advertising or publicity + * pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "xwayland.h" + +#include <stdio.h> + +#include <selection.h> +#include <micmap.h> +#include <misyncshm.h> +#include <compositeext.h> +#include <glx_extinit.h> + +void +ddxGiveUp(enum ExitCode error) +{ +} + +void +AbortDDX(enum ExitCode error) +{ + ddxGiveUp(error); +} + +void +OsVendorInit(void) +{ +} + +void +OsVendorFatalError(const char *f, va_list args) +{ +} + +#if defined(DDXBEFORERESET) +void +ddxBeforeReset(void) +{ + return; +} +#endif + +void +ddxUseMsg(void) +{ + ErrorF("-rootless run rootless, requires wm support\n"); + ErrorF("-wm fd create X client for wm on given fd\n"); + ErrorF("-listen fd add give fd as a listen socket\n"); +} + +int +ddxProcessArgument(int argc, char *argv[], int i) +{ + if (strcmp(argv[i], "-rootless") == 0) { + return 1; + } + else if (strcmp(argv[i], "-listen") == 0) { + NoListenAll = TRUE; + return 2; + } + else if (strcmp(argv[i], "-wm") == 0) { + return 2; + } + else if (strcmp(argv[i], "-shm") == 0) { + return 1; + } + + return 0; +} + +static DevPrivateKeyRec xwl_window_private_key; +static DevPrivateKeyRec xwl_screen_private_key; +static DevPrivateKeyRec xwl_pixmap_private_key; + +struct xwl_screen * +xwl_screen_get(ScreenPtr screen) +{ + return dixLookupPrivate(&screen->devPrivates, &xwl_screen_private_key); +} + +static Bool +xwl_close_screen(ScreenPtr screen) +{ + struct xwl_screen *xwl_screen = xwl_screen_get(screen); + struct xwl_output *xwl_output, *next_xwl_output; + struct xwl_seat *xwl_seat, *next_xwl_seat; + + xorg_list_for_each_entry_safe(xwl_output, next_xwl_output, + &xwl_screen->output_list, link) + xwl_output_destroy(xwl_output); + + xorg_list_for_each_entry_safe(xwl_seat, next_xwl_seat, + &xwl_screen->seat_list, link) + xwl_seat_destroy(xwl_seat); + + wl_display_disconnect(xwl_screen->display); + + screen->CloseScreen = xwl_screen->CloseScreen; + free(xwl_screen); + + return screen->CloseScreen(screen); +} + +static void +damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data) +{ + struct xwl_window *xwl_window = data; + struct xwl_screen *xwl_screen = xwl_window->xwl_screen; + + xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list); +} + +static void +damage_destroy(DamagePtr pDamage, void *data) +{ +} + +static void +shell_surface_ping(void *data, + struct wl_shell_surface *shell_surface, uint32_t serial) +{ + wl_shell_surface_pong(shell_surface, serial); +} + +static void +shell_surface_configure(void *data, + struct wl_shell_surface *wl_shell_surface, + uint32_t edges, int32_t width, int32_t height) +{ +} + +static void +shell_surface_popup_done(void *data, struct wl_shell_surface *wl_shell_surface) +{ +} + +static const struct wl_shell_surface_listener shell_surface_listener = { + shell_surface_ping, + shell_surface_configure, + shell_surface_popup_done +}; + +void +xwl_pixmap_set_private(PixmapPtr pixmap, struct xwl_pixmap *xwl_pixmap) +{ + dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key, xwl_pixmap); +} + +struct xwl_pixmap * +xwl_pixmap_get(PixmapPtr pixmap) +{ + return dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key); +} + +static void +send_surface_id_event(struct xwl_window *xwl_window) +{ + static const char atom_name[] = "WL_SURFACE_ID"; + static Atom type_atom; + DeviceIntPtr dev; + xEvent e; + + if (type_atom == None) + type_atom = MakeAtom(atom_name, strlen(atom_name), TRUE); + + e.u.u.type = ClientMessage; + e.u.u.detail = 32; + e.u.clientMessage.window = xwl_window->window->drawable.id; + e.u.clientMessage.u.l.type = type_atom; + e.u.clientMessage.u.l.longs0 = + wl_proxy_get_id((struct wl_proxy *) xwl_window->surface); + e.u.clientMessage.u.l.longs1 = 0; + e.u.clientMessage.u.l.longs2 = 0; + e.u.clientMessage.u.l.longs3 = 0; + e.u.clientMessage.u.l.longs4 = 0; + + dev = PickPointer(serverClient); + DeliverEventsToWindow(dev, xwl_window->xwl_screen->screen->root, + &e, 1, SubstructureRedirectMask, NullGrab); +} + +static Bool +xwl_realize_window(WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + struct xwl_screen *xwl_screen; + struct xwl_window *xwl_window; + struct wl_region *region; + Bool ret; + + xwl_screen = xwl_screen_get(screen); + + screen->RealizeWindow = xwl_screen->RealizeWindow; + ret = (*screen->RealizeWindow) (window); + xwl_screen->RealizeWindow = screen->RealizeWindow; + screen->RealizeWindow = xwl_realize_window; + + if (xwl_screen->rootless && !window->parent) { + ErrorF("Clearing root clip\n"); + RegionNull(&window->clipList); + RegionNull(&window->borderClip); + RegionNull(&window->winSize); + } + + if (xwl_screen->rootless) { + if (window->redirectDraw != RedirectDrawManual) + return ret; + } + else { + if (window->parent) + return ret; + } + + xwl_window = calloc(sizeof *xwl_window, 1); + xwl_window->xwl_screen = xwl_screen; + xwl_window->window = window; + xwl_window->surface = wl_compositor_create_surface(xwl_screen->compositor); + if (xwl_window->surface == NULL) { + ErrorF("wl_display_create_surface failed\n"); + return FALSE; + } + + if (!xwl_screen->rootless) { + xwl_window->shell_surface = + wl_shell_get_shell_surface(xwl_screen->shell, xwl_window->surface); + wl_shell_surface_add_listener(xwl_window->shell_surface, + &shell_surface_listener, xwl_window); + + wl_shell_surface_set_toplevel(xwl_window->shell_surface); + + region = wl_compositor_create_region(xwl_screen->compositor); + wl_region_add(region, 0, 0, + window->drawable.width, window->drawable.height); + wl_surface_set_opaque_region(xwl_window->surface, region); + wl_region_destroy(region); + } + + wl_display_flush(xwl_screen->display); + + send_surface_id_event(xwl_window); + + wl_surface_set_user_data(xwl_window->surface, xwl_window); + + dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window); + + xwl_window->damage = + DamageCreate(damage_report, damage_destroy, DamageReportNonEmpty, + FALSE, screen, xwl_window); + DamageRegister(&window->drawable, xwl_window->damage); + DamageSetReportAfterOp(xwl_window->damage, TRUE); + + xorg_list_init(&xwl_window->link_damage); + + return ret; +} + +static Bool +xwl_unrealize_window(WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + struct xwl_screen *xwl_screen; + struct xwl_window *xwl_window; + struct xwl_seat *xwl_seat; + Bool ret; + + xwl_screen = xwl_screen_get(screen); + + xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) { + if (!xwl_seat->focus_window) + continue; + if (xwl_seat->focus_window->window == window) + xwl_seat->focus_window = NULL; + } + + screen->UnrealizeWindow = xwl_screen->UnrealizeWindow; + ret = (*screen->UnrealizeWindow) (window); + xwl_screen->UnrealizeWindow = screen->UnrealizeWindow; + screen->UnrealizeWindow = xwl_unrealize_window; + + xwl_window = + dixLookupPrivate(&window->devPrivates, &xwl_window_private_key); + if (!xwl_window) + return ret; + + wl_surface_destroy(xwl_window->surface); + if (RegionNotEmpty(DamageRegion(xwl_window->damage))) + xorg_list_del(&xwl_window->link_damage); + DamageUnregister(xwl_window->damage); + DamageDestroy(xwl_window->damage); + free(xwl_window); + dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL); + + return ret; +} + +static Bool +xwl_save_screen(ScreenPtr pScreen, int on) +{ + return TRUE; +} + +static void +xwl_screen_post_damage(struct xwl_screen *xwl_screen) +{ + struct xwl_window *xwl_window; + RegionPtr region; + BoxPtr box; + int count, i; + struct wl_buffer *buffer; + PixmapPtr pixmap; + + xorg_list_for_each_entry(xwl_window, &xwl_screen->damage_window_list, + link_damage) { + region = DamageRegion(xwl_window->damage); + count = RegionNumRects(region); + + pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window); + + buffer = xwl_shm_pixmap_get_wl_buffer(pixmap); + wl_surface_attach(xwl_window->surface, buffer, 0, 0); + for (i = 0; i < count; i++) { + box = &RegionRects(region)[i]; + wl_surface_damage(xwl_window->surface, + box->x1, box->y1, + box->x2 - box->x1, box->y2 - box->y1); + } + wl_surface_commit(xwl_window->surface); + DamageEmpty(xwl_window->damage); + } + + xorg_list_init(&xwl_screen->damage_window_list); +} + +static void +registry_global(void *data, struct wl_registry *registry, uint32_t id, + const char *interface, uint32_t version) +{ + struct xwl_screen *xwl_screen = data; + + if (strcmp(interface, "wl_compositor") == 0) { + xwl_screen->compositor = + wl_registry_bind(registry, id, &wl_compositor_interface, 1); + } + else if (strcmp(interface, "wl_shm") == 0) { + xwl_screen->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); + } + else if (strcmp(interface, "wl_shell") == 0) { + xwl_screen->shell = + wl_registry_bind(registry, id, &wl_shell_interface, 1); + } + else if (strcmp(interface, "wl_output") == 0 && version >= 2) { + xwl_output_create(xwl_screen, id); + xwl_screen->expecting_event++; + } +} + +static void +global_remove(void *data, struct wl_registry *registry, uint32_t name) +{ + /* Nothing to do here, wl_compositor and wl_shm should not be removed */ +} + +static const struct wl_registry_listener registry_listener = { + registry_global, + global_remove +}; + +static void +wakeup_handler(void *data, int err, void *read_mask) +{ + struct xwl_screen *xwl_screen = data; + int ret; + + if (err < 0) + return; + + if (!FD_ISSET(xwl_screen->wayland_fd, (fd_set *) read_mask)) + return; + + ret = wl_display_read_events(xwl_screen->display); + if (ret == -1) + FatalError("failed to dispatch Wayland events: %s\n", strerror(errno)); + + xwl_screen->prepare_read = 0; + + ret = wl_display_dispatch_pending(xwl_screen->display); + if (ret == -1) + FatalError("failed to dispatch Wayland events: %s\n", strerror(errno)); +} + +static void +block_handler(void *data, struct timeval **tv, void *read_mask) +{ + struct xwl_screen *xwl_screen = data; + int ret; + + xwl_screen_post_damage(xwl_screen); + + while (xwl_screen->prepare_read == 0 && + wl_display_prepare_read(xwl_screen->display) == -1) { + ret = wl_display_dispatch_pending(xwl_screen->display); + if (ret == -1) + FatalError("failed to dispatch Wayland events: %s\n", + strerror(errno)); + } + + xwl_screen->prepare_read = 1; + + ret = wl_display_flush(xwl_screen->display); + if (ret == -1) + FatalError("failed to write to XWayland fd: %s\n", strerror(errno)); +} + +static CARD32 +add_client_fd(OsTimerPtr timer, CARD32 time, void *arg) +{ + struct xwl_screen *xwl_screen = arg; + + if (!AddClientOnOpenFD(xwl_screen->wm_fd)) + FatalError("Failed to add wm client\n"); + + TimerFree(timer); + + return 0; +} + +static void +listen_on_fds(struct xwl_screen *xwl_screen) +{ + int i; + + for (i = 0; i < xwl_screen->listen_fd_count; i++) + ListenOnOpenFD(xwl_screen->listen_fds[i], TRUE); +} + +static void +wm_selection_callback(CallbackListPtr *p, void *data, void *arg) +{ + SelectionInfoRec *info = arg; + struct xwl_screen *xwl_screen = data; + static const char atom_name[] = "WM_S0"; + static Atom atom_wm_s0; + + if (atom_wm_s0 == None) + atom_wm_s0 = MakeAtom(atom_name, strlen(atom_name), TRUE); + if (info->selection->selection != atom_wm_s0 || + info->kind != SelectionSetOwner) + return; + + listen_on_fds(xwl_screen); + + DeleteCallback(&SelectionCallback, wm_selection_callback, xwl_screen); +} + +static Bool +xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) +{ + struct xwl_screen *xwl_screen; + Pixel red_mask, blue_mask, green_mask; + int ret, bpc, green_bpc, i; + + xwl_screen = calloc(sizeof *xwl_screen, 1); + xwl_screen->wm_fd = -1; + if (xwl_screen == NULL) + return FALSE; + + if (!dixRegisterPrivateKey(&xwl_screen_private_key, PRIVATE_SCREEN, 0)) + return FALSE; + if (!dixRegisterPrivateKey(&xwl_window_private_key, PRIVATE_WINDOW, 0)) + return FALSE; + if (!dixRegisterPrivateKey(&xwl_pixmap_private_key, PRIVATE_PIXMAP, 0)) + return FALSE; + + dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen); + xwl_screen->screen = pScreen; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-rootless") == 0) { + xwl_screen->rootless = 1; + } + else if (strcmp(argv[i], "-wm") == 0) { + xwl_screen->wm_fd = atoi(argv[i + 1]); + i++; + TimerSet(NULL, 0, 1, add_client_fd, xwl_screen); + } + else if (strcmp(argv[i], "-listen") == 0) { + if (xwl_screen->listen_fd_count == + ARRAY_SIZE(xwl_screen->listen_fds)) + FatalError("Too many -listen arguments given, max is %ld\n", + ARRAY_SIZE(xwl_screen->listen_fds)); + + xwl_screen->listen_fds[xwl_screen->listen_fd_count++] = + atoi(argv[i + 1]); + i++; + } + } + + if (xwl_screen->listen_fd_count > 0) { + if (xwl_screen->wm_fd >= 0) + AddCallback(&SelectionCallback, wm_selection_callback, xwl_screen); + else + listen_on_fds(xwl_screen); + } + + xorg_list_init(&xwl_screen->output_list); + xorg_list_init(&xwl_screen->seat_list); + xorg_list_init(&xwl_screen->damage_window_list); + xwl_screen->depth = 24; + + xwl_screen->display = wl_display_connect(NULL); + if (xwl_screen->display == NULL) { + ErrorF("could not connect to wayland server\n"); + return FALSE; + } + + if (!xwl_screen_init_output(xwl_screen)) + return FALSE; + + xwl_screen->expecting_event = 0; + xwl_screen->registry = wl_display_get_registry(xwl_screen->display); + wl_registry_add_listener(xwl_screen->registry, + ®istry_listener, xwl_screen); + ret = wl_display_roundtrip(xwl_screen->display); + if (ret == -1) { + ErrorF("could not connect to wayland server\n"); + return FALSE; + } + + while (xwl_screen->expecting_event > 0) + wl_display_roundtrip(xwl_screen->display); + + bpc = xwl_screen->depth / 3; + green_bpc = xwl_screen->depth - 2 * bpc; + blue_mask = (1 << bpc) - 1; + green_mask = ((1 << green_bpc) - 1) << bpc; + red_mask = blue_mask << (green_bpc + bpc); + + miSetVisualTypesAndMasks(xwl_screen->depth, + ((1 << TrueColor) | (1 << DirectColor)), + green_bpc, TrueColor, + red_mask, green_mask, blue_mask); + + miSetPixmapDepths(); + + ret = fbScreenInit(pScreen, NULL, + xwl_screen->width, xwl_screen->height, + 96, 96, 0, + BitsPerPixel(xwl_screen->depth)); + if (!ret) + return FALSE; + + fbPictureInit(pScreen, 0, 0); + + if (!miSyncShmScreenInit(pScreen)) + return FALSE; + + xwl_screen->wayland_fd = wl_display_get_fd(xwl_screen->display); + AddGeneralSocket(xwl_screen->wayland_fd); + RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, xwl_screen); + + pScreen->SaveScreen = xwl_save_screen; + + pScreen->blackPixel = 0; + pScreen->whitePixel = 1; + + ret = fbCreateDefColormap(pScreen); + + if (!xwl_screen_init_cursor(xwl_screen)) + return FALSE; + + xwl_screen->CreateScreenResources = pScreen->CreateScreenResources; + pScreen->CreateScreenResources = xwl_shm_create_screen_resources; + pScreen->CreatePixmap = xwl_shm_create_pixmap; + pScreen->DestroyPixmap = xwl_shm_destroy_pixmap; + + xwl_screen->RealizeWindow = pScreen->RealizeWindow; + pScreen->RealizeWindow = xwl_realize_window; + + xwl_screen->UnrealizeWindow = pScreen->UnrealizeWindow; + pScreen->UnrealizeWindow = xwl_unrealize_window; + + xwl_screen->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = xwl_close_screen; + + return ret; +} + +static void _X_ATTRIBUTE_PRINTF(1, 0) +xwl_log_handler(const char *format, va_list args) +{ + char msg[256]; + + vsnprintf(msg, sizeof msg, format, args); + FatalError("%s", msg); +} + +static const ExtensionModule glx_extension[] = { + { GlxExtensionInit, "GLX", &noGlxExtension }, +}; + +void +InitOutput(ScreenInfo * screen_info, int argc, char **argv) +{ + int depths[] = { 1, 4, 8, 15, 16, 24, 32 }; + int bpp[] = { 1, 8, 8, 16, 16, 32, 32 }; + int i; + + for (i = 0; i < ARRAY_SIZE(depths); i++) { + screen_info->formats[i].depth = depths[i]; + screen_info->formats[i].bitsPerPixel = bpp[i]; + screen_info->formats[i].scanlinePad = BITMAP_SCANLINE_PAD; + } + + screen_info->imageByteOrder = IMAGE_BYTE_ORDER; + screen_info->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + screen_info->bitmapScanlinePad = BITMAP_SCANLINE_PAD; + screen_info->bitmapBitOrder = BITMAP_BIT_ORDER; + screen_info->numPixmapFormats = ARRAY_SIZE(depths); + + LoadExtensionList(glx_extension, ARRAY_SIZE(glx_extension), FALSE); + + /* Cast away warning from missing printf annotation for + * wl_log_func_t. Wayland 1.5 will have the annotation, so we can + * remove the cast and require that when it's released. */ + wl_log_set_handler_client((void *) xwl_log_handler); + + if (AddScreen(xwl_screen_init, argc, argv) == -1) { + FatalError("Couldn't add screen\n"); + } +} diff --git a/xorg-server/hw/xwayland/xwayland.h b/xorg-server/hw/xwayland/xwayland.h new file mode 100644 index 000000000..8157e71ff --- /dev/null +++ b/xorg-server/hw/xwayland/xwayland.h @@ -0,0 +1,164 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of the + * copyright holders not be used in advertising or publicity + * pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef XWAYLAND_H +#define XWAYLAND_H + +#include <dix-config.h> +#include <xorg-server.h> + +#include <stdio.h> +#include <unistd.h> +#include <errno.h> + +#include <wayland-client.h> + +#include <X11/X.h> + +#include <fb.h> +#include <input.h> +#include <dix.h> +#include <randrstr.h> +#include <exevents.h> + +struct xwl_screen { + int width; + int height; + int depth; + ScreenPtr screen; + WindowPtr pointer_limbo_window; + int expecting_event; + + int wm_fd; + int listen_fds[5]; + int listen_fd_count; + int rootless; + + CreateScreenResourcesProcPtr CreateScreenResources; + CloseScreenProcPtr CloseScreen; + CreateWindowProcPtr CreateWindow; + DestroyWindowProcPtr DestroyWindow; + RealizeWindowProcPtr RealizeWindow; + UnrealizeWindowProcPtr UnrealizeWindow; + XYToWindowProcPtr XYToWindow; + + struct xorg_list output_list; + struct xorg_list seat_list; + struct xorg_list damage_window_list; + + int wayland_fd; + struct wl_display *display; + struct wl_registry *registry; + struct wl_registry *input_registry; + struct wl_compositor *compositor; + struct wl_shm *shm; + struct wl_shell *shell; + + uint32_t serial; + +#define XWL_FORMAT_ARGB8888 (1 << 0) +#define XWL_FORMAT_XRGB8888 (1 << 1) +#define XWL_FORMAT_RGB565 (1 << 2) + + int prepare_read; +}; + +struct xwl_window { + struct xwl_screen *xwl_screen; + struct wl_surface *surface; + struct wl_shell_surface *shell_surface; + WindowPtr window; + DamagePtr damage; + struct xorg_list link_damage; +}; + +#define MODIFIER_META 0x01 + +struct xwl_seat { + DeviceIntPtr pointer; + DeviceIntPtr keyboard; + struct xwl_screen *xwl_screen; + struct wl_seat *seat; + struct wl_pointer *wl_pointer; + struct wl_keyboard *wl_keyboard; + struct wl_array keys; + struct wl_surface *cursor; + struct xwl_window *focus_window; + uint32_t id; + uint32_t pointer_enter_serial; + struct xorg_list link; + CursorPtr x_cursor; + + wl_fixed_t horizontal_scroll; + wl_fixed_t vertical_scroll; + uint32_t scroll_time; + + size_t keymap_size; + char *keymap; + struct wl_surface *keyboard_focus; +}; + +struct xwl_output { + struct xorg_list link; + struct wl_output *output; + struct xwl_screen *xwl_screen; + RROutputPtr randr_output; + RRCrtcPtr randr_crtc; + int32_t x, y, width, height; + Rotation rotation; +}; + +struct xwl_pixmap; + +Bool xwl_screen_init_cursor(struct xwl_screen *xwl_screen); + +struct xwl_screen *xwl_screen_get(ScreenPtr screen); + +void xwl_seat_set_cursor(struct xwl_seat *xwl_seat); + +void xwl_seat_destroy(struct xwl_seat *xwl_seat); + +Bool xwl_screen_init_output(struct xwl_screen *xwl_screen); + +struct xwl_output *xwl_output_create(struct xwl_screen *xwl_screen, + uint32_t id); + +void xwl_output_destroy(struct xwl_output *xwl_output); + +RRModePtr xwayland_cvt(int HDisplay, int VDisplay, + float VRefresh, Bool Reduced, Bool Interlaced); + +void xwl_pixmap_set_private(PixmapPtr pixmap, struct xwl_pixmap *xwl_pixmap); +struct xwl_pixmap *xwl_pixmap_get(PixmapPtr pixmap); + + +Bool xwl_shm_create_screen_resources(ScreenPtr screen); +PixmapPtr xwl_shm_create_pixmap(ScreenPtr screen, int width, int height, + int depth, unsigned int hint); +Bool xwl_shm_destroy_pixmap(PixmapPtr pixmap); +struct wl_buffer *xwl_shm_pixmap_get_wl_buffer(PixmapPtr pixmap); + + +#endif diff --git a/xorg-server/hw/xwin/Makefile.am b/xorg-server/hw/xwin/Makefile.am index 7f0eaf097..cf42cfd2d 100644 --- a/xorg-server/hw/xwin/Makefile.am +++ b/xorg-server/hw/xwin/Makefile.am @@ -127,10 +127,7 @@ SRCS = InitInput.c \ winresource.h \ winwindow.h \ XWin.rc \ - $(top_srcdir)/Xext/dpmsstubs.c \ - $(top_srcdir)/Xi/stubs.c \ $(top_srcdir)/mi/miinitext.c \ - $(top_srcdir)/fb/fbcmap_mi.c \ $(SRCS_CLIPBOARD) \ $(SRCS_MULTIWINDOW) \ $(SRCS_MULTIWINDOWEXTWM) \ @@ -153,12 +150,14 @@ XWin_SOURCES = $(SRCS) AM_CPPFLAGS = -I$(top_srcdir)/miext/rootless XWIN_SYS_LIBS += -ldxguid -XWIN_LIBS += $(top_builddir)/pseudoramiX/libPseudoramiX.la - +XWIN_LIBS += $(top_builddir)/pseudoramiX/libPseudoramiX.la \ + $(top_builddir)/Xext/libXextdpmsstubs.la \ + $(top_builddir)/Xi/libXistubs.la XWin_DEPENDENCIES = $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(XSERVER_LIBS) XWin_LDADD = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_GLX_LINK_FLAGS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS) XWin_LDFLAGS = -mwindows -static -Wl,--disable-stdcall-fixup + .rc.o: $(AM_V_GEN)$(WINDRES) --use-temp-file -i $< --input-format=rc -o $@ -O coff -I $(top_builddir)/include diff --git a/xorg-server/include/input.h b/xorg-server/include/input.h index 36463f2d1..cbf949b53 100644 --- a/xorg-server/include/input.h +++ b/xorg-server/include/input.h @@ -607,6 +607,7 @@ extern int GetXI2MaskByte(XI2Mask *mask, DeviceIntPtr dev, int event_type); void FixUpEventFromWindow(SpritePtr pSprite, xEvent *xE, WindowPtr pWin, Window child, Bool calcChild); +extern Bool PointInBorderSize(WindowPtr pWin, int x, int y); extern WindowPtr XYToWindow(SpritePtr pSprite, int x, int y); extern int EventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win); extern Bool ActivatePassiveGrab(DeviceIntPtr dev, GrabPtr grab, diff --git a/xorg-server/include/opaque.h b/xorg-server/include/opaque.h index 7ec1d850f..6b8071c5b 100644 --- a/xorg-server/include/opaque.h +++ b/xorg-server/include/opaque.h @@ -51,6 +51,7 @@ extern _X_EXPORT int defaultScreenSaverBlanking; extern _X_EXPORT int defaultScreenSaverAllowExposures; extern _X_EXPORT const char *display; extern _X_EXPORT int displayfd; +extern _X_EXPORT Bool explicit_display; extern _X_EXPORT int defaultBackingStore; extern _X_EXPORT Bool disableBackingStore; diff --git a/xorg-server/include/scrnintstr.h b/xorg-server/include/scrnintstr.h index 86da78966..6acdadd7a 100644 --- a/xorg-server/include/scrnintstr.h +++ b/xorg-server/include/scrnintstr.h @@ -353,6 +353,11 @@ typedef Bool (*StopPixmapTrackingProcPtr)(PixmapPtr, PixmapPtr); typedef Bool (*ReplaceScanoutPixmapProcPtr)(DrawablePtr, PixmapPtr, Bool); +typedef WindowPtr (*XYToWindowProcPtr)(ScreenPtr pScreen, + SpritePtr pSprite, int x, int y); + +typedef int (*NameWindowPixmapProcPtr)(WindowPtr, PixmapPtr, CARD32); + typedef struct _Screen { int myNum; /* index of this instance in Screens[] */ ATOM id; @@ -463,6 +468,7 @@ typedef struct _Screen { SetWindowPixmapProcPtr SetWindowPixmap; GetScreenPixmapProcPtr GetScreenPixmap; SetScreenPixmapProcPtr SetScreenPixmap; + NameWindowPixmapProcPtr NameWindowPixmap; PixmapPtr pScratchPixmap; /* scratch pixmap "pool" */ @@ -513,6 +519,7 @@ typedef struct _Screen { struct xorg_list offload_head; ReplaceScanoutPixmapProcPtr ReplaceScanoutPixmap; + XYToWindowProcPtr XYToWindow; } ScreenRec; static inline RegionPtr diff --git a/xorg-server/include/xorg-config.h.in b/xorg-server/include/xorg-config.h.in index 77a1aae55..629ae4057 100644 --- a/xorg-server/include/xorg-config.h.in +++ b/xorg-server/include/xorg-config.h.in @@ -45,9 +45,18 @@ /* Path to installed libraries. */ #undef DEFAULT_LIBRARY_PATH -/* Path to server log file. */ +/* Default log location */ +#undef DEFAULT_LOGDIR + +/* Default logfile prefix */ #undef DEFAULT_LOGPREFIX +/* Default XDG_DATA dir under HOME */ +#undef DEFAULT_XDG_DATA_HOME + +/* Default log dir under XDG_DATA_HOME */ +#undef DEFAULT_XDG_DATA_HOME_LOGDIR + /* Building DRI-capable DDX. */ #undef XF86DRI diff --git a/xorg-server/include/xwin-config.h.in b/xorg-server/include/xwin-config.h.in index 176c01980..a5e6b17b3 100644 --- a/xorg-server/include/xwin-config.h.in +++ b/xorg-server/include/xwin-config.h.in @@ -26,8 +26,5 @@ /* Vendor web address for support */ #undef __VENDORDWEBSUPPORT__ -/* Default log location */ -#undef DEFAULT_LOGDIR - /* Whether we should re-locate the root to where the executable lives */ #undef RELOCATE_PROJECTROOT diff --git a/xorg-server/mi/mi.h b/xorg-server/mi/mi.h index 950ee3812..1209a16c4 100644 --- a/xorg-server/mi/mi.h +++ b/xorg-server/mi/mi.h @@ -507,6 +507,10 @@ extern _X_EXPORT void miMarkUnrealizedWindow(WindowPtr /*pChild */ , extern _X_EXPORT void miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth); +extern _X_EXPORT WindowPtr miSpriteTrace(SpritePtr pSprite, int x, int y); + +extern _X_EXPORT WindowPtr miXYToWindow(ScreenPtr pScreen, SpritePtr pSprite, int x, int y); + /* mizerarc.c */ extern _X_EXPORT void miZeroPolyArc(DrawablePtr /*pDraw */ , diff --git a/xorg-server/mi/miscrinit.c b/xorg-server/mi/miscrinit.c index 6aed52f51..00c15f713 100644 --- a/xorg-server/mi/miscrinit.c +++ b/xorg-server/mi/miscrinit.c @@ -272,6 +272,7 @@ miScreenInit(ScreenPtr pScreen, void *pbits, /* pointer to screen bits */ pScreen->ChangeBorderWidth = miChangeBorderWidth; pScreen->SetShape = miSetShape; pScreen->MarkUnrealizedWindow = miMarkUnrealizedWindow; + pScreen->XYToWindow = miXYToWindow; miSetZeroLineBias(pScreen, DEFAULTZEROLINEBIAS); diff --git a/xorg-server/mi/miwindow.c b/xorg-server/mi/miwindow.c index 697ffbc26..951b8c519 100644 --- a/xorg-server/mi/miwindow.c +++ b/xorg-server/mi/miwindow.c @@ -57,6 +57,7 @@ SOFTWARE. #include "scrnintstr.h" #include "pixmapstr.h" #include "mivalidate.h" +#include "inputstr.h" void miClearToBackground(WindowPtr pWin, @@ -758,3 +759,68 @@ miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth) miSegregateChildren(pChild, pReg, depth); } } + +WindowPtr +miSpriteTrace(SpritePtr pSprite, int x, int y) +{ + WindowPtr pWin; + BoxRec box; + + pWin = DeepestSpriteWin(pSprite); + while (pWin) { + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth(pWin)) && + (x < pWin->drawable.x + (int) pWin->drawable.width + + wBorderWidth(pWin)) && + (y >= pWin->drawable.y - wBorderWidth(pWin)) && + (y < pWin->drawable.y + (int) pWin->drawable.height + + wBorderWidth(pWin)) + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y)) + && (!wInputShape(pWin) || + RegionContainsPoint(wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box)) +#ifdef ROOTLESS + /* In rootless mode windows may be offscreen, even when + * they're in X's stack. (E.g. if the native window system + * implements some form of virtual desktop system). + */ + && !pWin->rootlessUnhittable +#endif + ) { + if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) { + pSprite->spriteTraceSize += 10; + pSprite->spriteTrace = realloc(pSprite->spriteTrace, + pSprite->spriteTraceSize * + sizeof(WindowPtr)); + } + pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin; + pWin = pWin->firstChild; + } + else + pWin = pWin->nextSib; + } + return DeepestSpriteWin(pSprite); +} + +/** + * Traversed from the root window to the window at the position x/y. While + * traversing, it sets up the traversal history in the spriteTrace array. + * After completing, the spriteTrace history is set in the following way: + * spriteTrace[0] ... root window + * spriteTrace[1] ... top level window that encloses x/y + * ... + * spriteTrace[spriteTraceGood - 1] ... window at x/y + * + * @returns the window at the given coordinates. + */ +WindowPtr +miXYToWindow(ScreenPtr pScreen, SpritePtr pSprite, int x, int y) +{ + pSprite->spriteTraceGood = 1; /* root window still there */ + return miSpriteTrace(pSprite, x, y); +} diff --git a/xorg-server/os/connection.c b/xorg-server/os/connection.c index b3640b8e4..e914d9d94 100644 --- a/xorg-server/os/connection.c +++ b/xorg-server/os/connection.c @@ -352,8 +352,8 @@ void NotifyParentProcess(void) { #if !defined(WIN32) - if (dynamic_display[0]) { - write(displayfd, dynamic_display, strlen(dynamic_display)); + if (displayfd >= 0) { + write(displayfd, display, strlen(display)); write(displayfd, "\n", 1); close(displayfd); } @@ -405,18 +405,18 @@ CreateWellKnownSockets(void) FD_ZERO(&WellKnownConnections); /* display is initialized to "0" by main(). It is then set to the display - * number if specified on the command line, or to NULL when the -displayfd - * option is used. */ + * number if specified on the command line. */ + if (NoListenAll) { ListenTransCount = 0; } - else if (display) { + else if ((displayfd < 0) || explicit_display) { if (TryCreateSocket(atoi(display), &partial) && ListenTransCount >= 1) if (!PartialNetwork && partial) FatalError ("Failed to establish all listening sockets"); } - else { /* -displayfd */ + else { /* -displayfd and no explicit display number */ Bool found = 0; for (i = 0; i < 65535 - X_TCP_PORT; i++) { if (TryCreateSocket(i, &partial) && !partial) { diff --git a/xorg-server/os/utils.c b/xorg-server/os/utils.c index c513968ad..6e6974e89 100644 --- a/xorg-server/os/utils.c +++ b/xorg-server/os/utils.c @@ -666,6 +666,7 @@ ProcessCommandLine(int argc, char *argv[]) else if (argv[i][0] == ':') { /* initialize display */ display = argv[i]; + explicit_display = TRUE; display++; if (!VerifyDisplayName(display)) { ErrorF("Bad display name: %s\n", display); @@ -736,7 +737,6 @@ ProcessCommandLine(int argc, char *argv[]) else if (strcmp(argv[i], "-displayfd") == 0) { if (++i < argc) { displayfd = atoi(argv[i]); - display = NULL; #ifdef LOCK_SERVER nolock = TRUE; #endif diff --git a/xorg-server/test/Makefile.am b/xorg-server/test/Makefile.am index 88fb6aa96..3ad24d9ec 100644 --- a/xorg-server/test/Makefile.am +++ b/xorg-server/test/Makefile.am @@ -70,9 +70,7 @@ endif else nodist_libxservertest_la_SOURCES = \ ddxstubs.c \ - $(top_srcdir)/mi/miinitext.c \ - $(top_srcdir)/Xext/dpmsstubs.c \ - $(top_srcdir)/Xi/stubs.c + $(top_srcdir)/mi/miinitext.c libxservertest_la_LIBADD += \ $(top_builddir)/damageext/libdamageext.la \ @@ -83,7 +81,9 @@ libxservertest_la_LIBADD += \ $(top_builddir)/randr/librandr.la \ $(top_builddir)/render/librender.la \ $(top_builddir)/Xext/libXext.la \ + $(top_builddir)/Xext/libXextdpmsstubs.la \ $(top_builddir)/Xi/libXi.la \ + $(top_builddir)/Xi/libXistubs.la \ $(top_builddir)/xfixes/libxfixes.la \ $(top_builddir)/xkb/libxkb.la \ $(top_builddir)/xkb/libxkbstubs.la diff --git a/xorg-server/xkb/xkbAccessX.c b/xorg-server/xkb/xkbAccessX.c index cb4bca008..5f3de0d9e 100644 --- a/xorg-server/xkb/xkbAccessX.c +++ b/xorg-server/xkb/xkbAccessX.c @@ -711,7 +711,7 @@ ProcessPointerEvent(InternalEvent *ev, DeviceIntPtr mouse) xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(mouse); DeviceEvent *event = &ev->device_event; - dev = (IsMaster(mouse) || IsFloating(mouse)) ? mouse : GetMaster(mouse, MASTER_KEYBOARD); + dev = IsFloating(mouse) ? mouse : GetMaster(mouse, MASTER_KEYBOARD); if (dev && dev->key) { xkbi = dev->key->xkbInfo; |