diff options
Diffstat (limited to 'xorg-server')
62 files changed, 4075 insertions, 111 deletions
diff --git a/xorg-server/Makefile.am b/xorg-server/Makefile.am index 7be4271d4..5bf760b2e 100644 --- a/xorg-server/Makefile.am +++ b/xorg-server/Makefile.am @@ -17,6 +17,14 @@ if RECORD RECORD_DIR=record endif +if DRI3 +DRI3_DIR=dri3 +endif + +if PRESENT +PRESENT_DIR=present +endif + SUBDIRS = \ doc \ man \ @@ -38,6 +46,8 @@ SUBDIRS = \ damageext \ $(COMPOSITE_DIR) \ $(GLX_DIR) \ + $(PRESENT_DIR) \ + $(DRI3_DIR) \ exa \ config \ hw \ @@ -91,6 +101,8 @@ DIST_SUBDIRS = \ glx \ exa \ config \ + dri3 \ + present \ hw \ test diff --git a/xorg-server/Xext/shm.c b/xorg-server/Xext/shm.c index 55960907b..1a70260fb 100644 --- a/xorg-server/Xext/shm.c +++ b/xorg-server/Xext/shm.c @@ -53,6 +53,7 @@ in this Software without prior written authorization from The Open Group. #include "xace.h" #include <X11/extensions/shmproto.h> #include <X11/Xfuncproto.h> +#include <sys/mman.h> #include "protocol-versions.h" /* Needed for Solaris cross-zone shared memory extension */ @@ -89,15 +90,6 @@ in this Software without prior written authorization from The Open Group. #include "extinit.h" -typedef struct _ShmDesc { - struct _ShmDesc *next; - int shmid; - int refcnt; - char *addr; - Bool writable; - unsigned long size; -} ShmDescRec, *ShmDescPtr; - typedef struct _ShmScrPrivateRec { CloseScreenProcPtr CloseScreen; ShmFuncsPtr shmFuncs; @@ -391,8 +383,10 @@ ProcShmAttach(ClientPtr client) client->errorValue = stuff->readOnly; return BadValue; } - for (shmdesc = Shmsegs; - shmdesc && (shmdesc->shmid != stuff->shmid); shmdesc = shmdesc->next); + for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) { + if (!shmdesc->is_fd && shmdesc->shmid == stuff->shmid) + break; + } if (shmdesc) { if (!stuff->readOnly && !shmdesc->writable) return BadAccess; @@ -402,6 +396,7 @@ ProcShmAttach(ClientPtr client) shmdesc = malloc(sizeof(ShmDescRec)); if (!shmdesc) return BadAlloc; + shmdesc->is_fd = FALSE; shmdesc->addr = shmat(stuff->shmid, 0, stuff->readOnly ? SHM_RDONLY : 0); if ((shmdesc->addr == ((char *) -1)) || SHMSTAT(stuff->shmid, &buf)) { @@ -440,7 +435,10 @@ ShmDetachSegment(pointer value, /* must conform to DeleteType */ if (--shmdesc->refcnt) return TRUE; - shmdt(shmdesc->addr); + if (shmdesc->is_fd) + munmap(shmdesc->addr, shmdesc->size); + else + shmdt(shmdesc->addr); for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next); *prev = shmdesc->next; free(shmdesc); @@ -1097,6 +1095,122 @@ ProcShmCreatePixmap(ClientPtr client) } static int +ProcShmAttachFd(ClientPtr client) +{ + int fd; + ShmDescPtr shmdesc; + REQUEST(xShmAttachFdReq); + struct stat statb; + + SetReqFds(client, 1); + REQUEST_SIZE_MATCH(xShmAttachFdReq); + LEGAL_NEW_RESOURCE(stuff->shmseg, client); + if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) { + client->errorValue = stuff->readOnly; + return BadValue; + } + fd = ReadFdFromClient(client); + if (fd < 0) + return BadMatch; + + if (fstat(fd, &statb) < 0 || statb.st_size == 0) { + close(fd); + return BadMatch; + } + + shmdesc = malloc(sizeof(ShmDescRec)); + if (!shmdesc) { + close(fd); + return BadAlloc; + } + shmdesc->is_fd = TRUE; + shmdesc->addr = mmap(NULL, statb.st_size, + stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE, + MAP_SHARED, + fd, 0); + + close(fd); + if ((shmdesc->addr == ((char *) -1))) { + free(shmdesc); + return BadAccess; + } + + shmdesc->refcnt = 1; + shmdesc->writable = !stuff->readOnly; + shmdesc->size = statb.st_size; + shmdesc->next = Shmsegs; + Shmsegs = shmdesc; + + if (!AddResource(stuff->shmseg, ShmSegType, (pointer) shmdesc)) + return BadAlloc; + return Success; +} + +static int +ProcShmCreateSegment(ClientPtr client) +{ + int fd; + ShmDescPtr shmdesc; + REQUEST(xShmCreateSegmentReq); + xShmCreateSegmentReply rep = { + .type = X_Reply, + .nfd = 1, + .sequenceNumber = client->sequence, + .length = 0, + }; + char template[] = "/tmp/shm-XXXXXX"; + + REQUEST_SIZE_MATCH(xShmCreateSegmentReq); + if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) { + client->errorValue = stuff->readOnly; + return BadValue; + } + fd = mkstemp(template); + if (fd < 0) + return BadAlloc; + unlink(template); + if (ftruncate(fd, stuff->size) < 0) { + close(fd); + return BadAlloc; + } + shmdesc = malloc(sizeof(ShmDescRec)); + if (!shmdesc) { + close(fd); + return BadAlloc; + } + shmdesc->is_fd = TRUE; + shmdesc->addr = mmap(NULL, stuff->size, + stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE, + MAP_SHARED, + fd, 0); + + if ((shmdesc->addr == ((char *) -1))) { + close(fd); + free(shmdesc); + return BadAccess; + } + + shmdesc->refcnt = 1; + shmdesc->writable = !stuff->readOnly; + shmdesc->size = stuff->size; + shmdesc->next = Shmsegs; + Shmsegs = shmdesc; + + if (!AddResource(stuff->shmseg, ShmSegType, (pointer) shmdesc)) { + close(fd); + return BadAlloc; + } + + if (WriteFdToClient(client, fd, TRUE) < 0) { + FreeResource(stuff->shmseg, RT_NONE); + close(fd); + return BadAlloc; + } + WriteToClient(client, sizeof (xShmCreateSegmentReply), &rep); + return Success; +} + +static int ProcShmDispatch(ClientPtr client) { REQUEST(xReq); @@ -1125,6 +1239,10 @@ ProcShmDispatch(ClientPtr client) return ProcPanoramiXShmCreatePixmap(client); #endif return ProcShmCreatePixmap(client); + case X_ShmAttachFd: + return ProcShmAttachFd(client); + case X_ShmCreateSegment: + return ProcShmCreateSegment(client); default: return BadRequest; } @@ -1226,6 +1344,28 @@ SProcShmCreatePixmap(ClientPtr client) } static int +SProcShmAttachFd(ClientPtr client) +{ + REQUEST(xShmAttachFdReq); + SetReqFds(client, 1); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShmAttachFdReq); + swapl(&stuff->shmseg); + return ProcShmAttachFd(client); +} + +static int +SProcShmCreateSegment(ClientPtr client) +{ + REQUEST(xShmCreateSegmentReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShmCreateSegmentReq); + swapl(&stuff->shmseg); + swapl(&stuff->size); + return ProcShmCreateSegment(client); +} + +static int SProcShmDispatch(ClientPtr client) { REQUEST(xReq); @@ -1242,6 +1382,10 @@ SProcShmDispatch(ClientPtr client) return SProcShmGetImage(client); case X_ShmCreatePixmap: return SProcShmCreatePixmap(client); + case X_ShmAttachFd: + return SProcShmAttachFd(client); + case X_ShmCreateSegment: + return SProcShmCreateSegment(client); default: return BadRequest; } diff --git a/xorg-server/Xext/shmint.h b/xorg-server/Xext/shmint.h index fa6941c90..db35fbbbe 100644 --- a/xorg-server/Xext/shmint.h +++ b/xorg-server/Xext/shmint.h @@ -56,6 +56,16 @@ typedef struct _ShmFuncs { void (*PutImage) (XSHM_PUT_IMAGE_ARGS); } ShmFuncs, *ShmFuncsPtr; +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool is_fd; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + extern _X_EXPORT void ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs); diff --git a/xorg-server/Xext/sync.c b/xorg-server/Xext/sync.c index b2ee92e37..a04c38388 100644 --- a/xorg-server/Xext/sync.c +++ b/xorg-server/Xext/sync.c @@ -141,7 +141,7 @@ SyncCheckWarnIsCounter(const SyncObject * pSync, const char *warning) * interested in the counter. The two functions below are used to * delete and add triggers on this list. */ -static void +void SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger) { SyncTriggerList *pCur; @@ -184,7 +184,7 @@ SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger) } } -static int +int SyncAddTriggerToSyncObject(SyncTrigger * pTrigger) { SyncTriggerList *pCur; @@ -916,6 +916,34 @@ SyncCreate(ClientPtr client, XID id, unsigned char type) return pSync; } +int +SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL initially_triggered) +{ + SyncFence *pFence; + int status; + + pFence = (SyncFence *) SyncCreate(client, id, SYNC_FENCE); + if (!pFence) + return BadAlloc; + + status = miSyncInitFenceFromFD(pDraw, pFence, fd, initially_triggered); + if (status != Success) { + miSyncDestroyFence(pFence); + return status; + } + + if (!AddResource(id, RTFence, (pointer) pFence)) + return BadAlloc; + + return Success; +} + +int +SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *pFence) +{ + return miSyncFDFromFence(pDraw, pFence); +} + static SyncCounter * SyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue) { @@ -2654,7 +2682,16 @@ IdleTimeBlockHandler(pointer pCounter, struct timeval **wt, pointer LastSelectMa IdleTimeQueryValue(counter, &idle); counter->value = idle; /* push, so CheckTrigger works */ - if (less && XSyncValueLessOrEqual(idle, *less)) { + /** + * There's an indefinite amount of time between ProcessInputEvents() + * where the idle time is reset and the time we actually get here. idle + * may be past the lower bracket if we dawdled with the events, so + * check for whether we did reset and bomb out of select immediately. + */ + if (less && XSyncValueGreaterThan(idle, *less) && + LastEventTimeWasReset(priv->deviceid)) { + AdjustWaitForDelay(wt, 0); + } else if (less && XSyncValueLessOrEqual(idle, *less)) { /* * We've been idle for less than the threshold value, and someone * wants to know about that, but now we need to know whether they diff --git a/xorg-server/Xext/syncsrv.h b/xorg-server/Xext/syncsrv.h index c68229f46..45fca04da 100644 --- a/xorg-server/Xext/syncsrv.h +++ b/xorg-server/Xext/syncsrv.h @@ -136,4 +136,17 @@ extern void SyncDestroySystemCounter(pointer pCounter); extern SyncCounter *SyncInitDeviceIdleTime(DeviceIntPtr dev); extern void SyncRemoveDeviceIdleTime(SyncCounter *counter); + +int +SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL initially_triggered); + +int +SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *fence); + +void +SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger); + +int +SyncAddTriggerToSyncObject(SyncTrigger * pTrigger); + #endif /* _SYNCSRV_H_ */ diff --git a/xorg-server/Xext/xvdisp.c b/xorg-server/Xext/xvdisp.c index 787729387..613867a6b 100644 --- a/xorg-server/Xext/xvdisp.c +++ b/xorg-server/Xext/xvdisp.c @@ -43,6 +43,7 @@ SOFTWARE. #include "xvdix.h" #ifdef MITSHM #include <X11/extensions/shmproto.h> +#include "shmint.h" #endif #include "xvdisp.h" @@ -949,18 +950,6 @@ ProcXvPutImage(ClientPtr client) } #ifdef MITSHM -/* redefined here since it's not in any header file */ -typedef struct _ShmDesc { - struct _ShmDesc *next; - int shmid; - int refcnt; - char *addr; - Bool writable; - unsigned long size; -} ShmDescRec, *ShmDescPtr; - -extern RESTYPE ShmSegType; -extern int ShmCompletionCode; static int ProcXvShmPutImage(ClientPtr client) diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac index d29f1706a..0d855f250 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.14.99.3, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server) -RELEASE_DATE="2013-10-18" -RELEASE_NAME="Bundaberg" +AC_INIT([xorg-server], 1.14.99.901, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server) +RELEASE_DATE="2013-10-31" +RELEASE_NAME="Bom Retiro" AC_CONFIG_SRCDIR([Makefile.am]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) @@ -228,10 +228,6 @@ dnl AGPGART headers AC_CHECK_HEADERS([linux/agpgart.h sys/agpio.h sys/agpgart.h], AGP=yes) AM_CONDITIONAL(AGP, [test "x$AGP" = xyes]) -dnl APM header -AC_CHECK_HEADERS([linux/apm_bios.h], LNXAPM=yes) -AM_CONDITIONAL(LNXAPM, [test "x$LNXAPM" = xyes]) - dnl fbdev header AC_CHECK_HEADERS([linux/fb.h], FBDEV=yes) AM_CONDITIONAL(FBDEVHW, [test "x$FBDEV" = xyes]) @@ -300,7 +296,7 @@ AC_CHECK_HEADER([machine/apmvar.h],[ AM_CONDITIONAL(BSD_APM, [test "x$ac_cv_BSD_APM" = xyes]) AM_CONDITIONAL(BSD_KQUEUE_APM, [test "x$ac_cv_BSD_KQUEUE_APM" = xyes]) -dnl glibc backtrace support check (hw/xfree86/common/xf86Events.c) +dnl glibc backtrace support check AC_CHECK_HEADER([execinfo.h],[ AC_CHECK_LIB(c, backtrace, [ AC_DEFINE(HAVE_BACKTRACE, 1, [Has backtrace support]) @@ -613,6 +609,8 @@ AC_ARG_ENABLE(xdm-auth-1, AS_HELP_STRING([--disable-xdm-auth-1], [Build XDM- AC_ARG_ENABLE(glx, AS_HELP_STRING([--disable-glx], [Build GLX extension (default: enabled)]), [GLX=$enableval], [GLX=yes]) AC_ARG_ENABLE(dri, AS_HELP_STRING([--enable-dri], [Build DRI extension (default: auto)]), [DRI=$enableval]) AC_ARG_ENABLE(dri2, AS_HELP_STRING([--enable-dri2], [Build DRI2 extension (default: auto)]), [DRI2=$enableval], [DRI2=auto]) +AC_ARG_ENABLE(dri3, AS_HELP_STRING([--enable-dri3], [Build DRI3 extension (default: auto)]), [DRI3=$enableval], [DRI3=auto]) +AC_ARG_ENABLE(present, AS_HELP_STRING([--disable-present], [Build Present extension (default: enabled)]), [PRESENT=$enableval], [PRESENT=yes]) AC_ARG_ENABLE(xinerama, AS_HELP_STRING([--disable-xinerama], [Build Xinerama extension (default: enabled)]), [XINERAMA=$enableval], [XINERAMA=yes]) AC_ARG_ENABLE(xf86vidmode, AS_HELP_STRING([--disable-xf86vidmode], [Build XF86VidMode extension (default: auto)]), [XF86VIDMODE=$enableval], [XF86VIDMODE=auto]) AC_ARG_ENABLE(xace, AS_HELP_STRING([--disable-xace], [Build X-ACE extension (default: enabled)]), [XACE=$enableval], [XACE=yes]) @@ -635,6 +633,8 @@ AC_ARG_ENABLE(windowswm, AS_HELP_STRING([--enable-windowswm], [Build XWin w AC_ARG_ENABLE(libdrm, AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes]) AC_ARG_ENABLE(clientids, AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes]) 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, AC_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, AC_HELP_STRING([--disable-linux-apm], [Disable building APM support on Linux (if available).]), [enable_linux_apm=$enableval], [enable_linux_apm=yes]) dnl DDXes. AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto]) @@ -715,6 +715,7 @@ case $host_os in CONFIG_UDEV_KMS=no DGA=no DRI2=no + DRI3=no INT10MODULE=no PCI=no VGAHW=no @@ -732,6 +733,7 @@ case $host_os in VBE=no DRM=no DRI2=no + DRI3=no if test x$XQUARTZ = xauto; then AC_CACHE_CHECK([whether to build Xquartz],xorg_cv_Carbon_framework,[ @@ -781,6 +783,7 @@ SCRNSAVERPROTO="scrnsaverproto >= 1.1" RESOURCEPROTO="resourceproto >= 1.2.0" DRIPROTO="xf86driproto >= 2.1.0" DRI2PROTO="dri2proto >= 2.8" +DRI3PROTO="dri3proto >= 1.0" XINERAMAPROTO="xineramaproto" BIGFONTPROTO="xf86bigfontproto >= 1.2.0" DGAPROTO="xf86dgaproto >= 2.0.99.1" @@ -803,6 +806,7 @@ DAMAGEPROTO="damageproto >= 1.1" XCMISCPROTO="xcmiscproto >= 1.2.0" BIGREQSPROTO="bigreqsproto >= 1.1.0" XTRANS="xtrans >= 1.2.2" +PRESENTPROTO="presentproto >= 1.0" dnl List of libraries that require a specific version LIBAPPLEWM="applewm >= 1.4" @@ -1113,7 +1117,22 @@ case "$DRI2,$HAVE_DRI2PROTO" in esac AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes) -if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$CONFIG_UDEV_KMS" = xyes; then +PKG_CHECK_MODULES([DRI3PROTO], $DRI3PROTO, + [HAVE_DRI3PROTO=yes], [HAVE_DRI3PROTO=no]) +case "$DRI3,$HAVE_DRI3PROTO" in + yes,no) + AC_MSG_ERROR([DRI3 requested, but dri3proto not found.]) + ;; + yes,yes | auto,yes) + AC_DEFINE(DRI3, 1, [Build DRI3 extension]) + DRI3=yes + DRI3_LIB='$(top_builddir)/dri3/libdri3.la' + SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $DRI3PROTO" + ;; +esac +AM_CONDITIONAL(DRI3, test "x$DRI3" = xyes) + +if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$DRI3" = xyes || test "x$CONFIG_UDEV_KMS" = xyes; then if test "x$DRM" = xyes; then AC_DEFINE(WITH_LIBDRM, 1, [Building with libdrm support]) PKG_CHECK_MODULES([LIBDRM], $LIBDRM) @@ -1141,6 +1160,14 @@ if test "x$DRI2" = xyes; then fi AM_CONDITIONAL(DRI2_AIGLX, test "x$DRI2_AIGLX" = xyes) +AM_CONDITIONAL(PRESENT, [test "x$PRESENT" = xyes]) +if test "x$PRESENT" = xyes; then + AC_DEFINE(PRESENT, 1, [Support Present extension]) + REQUIRED_MODULES="$REQUIRED_MODULES $PRESENTPROTO" + SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $PRESENTPROTO" + PRESENT_INC='-I$(top_srcdir)/present' + PRESENT_LIB='$(top_builddir)/present/libpresent.la' +fi AM_CONDITIONAL(XINERAMA, [test "x$XINERAMA" = xyes]) if test "x$XINERAMA" = xyes; then @@ -1306,6 +1333,7 @@ if test "x$XDMAUTH" = xyes; then XDMCP_MODULES="xdmcp" fi fi +REQUIRED_LIBS="$REQUIRED_LIBS xshmfence" AC_DEFINE_DIR(COMPILEDDEFAULTFONTPATH, FONTPATH, [Default font path]) AC_DEFINE_DIR(SERVER_MISC_CONFIG_PATH, SERVERCONFIG, [Server miscellaneous config path]) @@ -1564,7 +1592,7 @@ AC_EGREP_CPP([I_AM_SVR4],[ AC_DEFINE([SVR4],1,[Define to 1 on systems derived from System V Release 4]) AC_MSG_RESULT([yes])], AC_MSG_RESULT([no])) -XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SYNC_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC $DBE_INC" +XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SYNC_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC $DBE_INC $PRESENT_INC" dnl --------------------------------------------------------------------------- dnl DDX section. @@ -1577,7 +1605,7 @@ AC_MSG_RESULT([$XVFB]) AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes]) if test "x$XVFB" = xyes; then - XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB" + XVFB_LIBS="$FB_LIB $FIXES_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" XVFB_SYS_LIBS="$XVFBMODULES_LIBS $GLX_SYS_LIBS" AC_SUBST([XVFB_LIBS]) AC_SUBST([XVFB_SYS_LIBS]) @@ -1598,7 +1626,7 @@ if test "x$XNEST" = xyes; then if test "x$have_xnest" = xno; then AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.]) fi - XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_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" + XNEST_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" XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS" AC_SUBST([XNEST_LIBS]) AC_SUBST([XNEST_SYS_LIBS]) @@ -1623,7 +1651,7 @@ if test "x$XORG" = xyes; then XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os' XORG_INCS="$XORG_DDXINCS $XORG_OSINCS" XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H" - XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB" + XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB" dnl ================================================================== dnl symbol visibility @@ -1705,9 +1733,6 @@ if test "x$XORG" = xyes; then case $host_os in linux*) - if test "x$LNXAPM" = xyes; then - XORG_CFLAGS="$XORG_CFLAGS -DXF86PM" - fi XORG_OS_SUBDIR="linux" linux_acpi="no" case $host_cpu in @@ -1715,11 +1740,16 @@ if test "x$XORG" = xyes; then linux_alpha=yes ;; i*86|amd64*|x86_64*|ia64*) - linux_acpi="yes" + linux_acpi=$enable_linux_acpi ;; *) ;; esac + dnl APM header + AC_CHECK_HEADERS([linux/apm_bios.h], [linux_apm=$enable_linux_apm]) + if test "x$linux_apm" = xyes -o "x$linux_acpi" = xyes; then + AC_DEFINE(XF86PM, 1, [Support APM/ACPI power management in the server]) + fi ;; freebsd* | kfreebsd*-gnu | dragonfly*) XORG_OS_SUBDIR="bsd" @@ -1882,6 +1912,7 @@ AM_CONDITIONAL([XORG_BUS_BSDPCI], [test "x$xorg_bus_bsdpci" = xyes]) AM_CONDITIONAL([XORG_BUS_SPARC], [test "x$xorg_bus_sparc" = xyes]) AM_CONDITIONAL([LINUX_ALPHA], [test "x$linux_alpha" = xyes]) AM_CONDITIONAL([LNXACPI], [test "x$linux_acpi" = xyes]) +AM_CONDITIONAL([LNXAPM], [test "x$linux_apm" = xyes]) AM_CONDITIONAL([SOLARIS_ASM_INLINE], [test "x$solaris_asm_inline" = xyes]) AM_CONDITIONAL([SOLARIS_VT], [test "x$solaris_vt" = xyes]) AM_CONDITIONAL([DGA], [test "x$DGA" = xyes]) @@ -2036,7 +2067,7 @@ if test "x$DMX" = xyes; then fi DMX_INCLUDES="$XEXT_INC $RENDER_INC $RECORD_INC" XDMX_CFLAGS="$DMXMODULES_CFLAGS" - XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB" + XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB" XDMX_SYS_LIBS="$DMXMODULES_LIBS" AC_SUBST([XDMX_CFLAGS]) AC_SUBST([XDMX_LIBS]) @@ -2145,7 +2176,7 @@ if test "$KDRIVE" = yes; then KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS" - KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB" + KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_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 $OS_LIB" KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.la' case $host_os in *linux*) @@ -2267,6 +2298,8 @@ Xext/Makefile Xi/Makefile xfixes/Makefile exa/Makefile +dri3/Makefile +present/Makefile hw/Makefile hw/xfree86/Makefile hw/xfree86/common/Makefile diff --git a/xorg-server/dix/region.c b/xorg-server/dix/region.c index 737d2a861..15f3d01a5 100644 --- a/xorg-server/dix/region.c +++ b/xorg-server/dix/region.c @@ -255,6 +255,21 @@ RegionDestroy(RegionPtr pReg) free(pReg); } +RegionPtr +RegionDuplicate(RegionPtr pOld) +{ + RegionPtr pNew; + + pNew = RegionCreate(&pOld->extents, 0); + if (!pNew) + return NULL; + if (!RegionCopy(pNew, pOld)) { + RegionDestroy(pNew); + return NULL; + } + return pNew; +} + void RegionPrint(RegionPtr rgn) { diff --git a/xorg-server/dri3/Makefile.am b/xorg-server/dri3/Makefile.am new file mode 100644 index 000000000..e47a734e0 --- /dev/null +++ b/xorg-server/dri3/Makefile.am @@ -0,0 +1,13 @@ +noinst_LTLIBRARIES = libdri3.la +AM_CFLAGS = \ + -DHAVE_XORG_CONFIG_H \ + @DIX_CFLAGS@ @XORG_CFLAGS@ + +libdri3_la_SOURCES = \ + dri3.h \ + dri3_priv.h \ + dri3.c \ + dri3_request.c \ + dri3_screen.c + +sdk_HEADERS = dri3.h diff --git a/xorg-server/dri3/dri3.c b/xorg-server/dri3/dri3.c new file mode 100644 index 000000000..2bca7ae9b --- /dev/null +++ b/xorg-server/dri3/dri3.c @@ -0,0 +1,87 @@ +/* + * Copyright © 2013 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "dri3_priv.h" + +int dri3_request; +DevPrivateKeyRec dri3_screen_private_key; +DevPrivateKeyRec dri3_window_private_key; + +static Bool +dri3_close_screen(ScreenPtr screen) +{ + dri3_screen_priv_ptr screen_priv = dri3_screen_priv(screen); + + unwrap(screen_priv, screen, CloseScreen); + + free(screen_priv); + return (*screen->CloseScreen) (screen); +} + +Bool +dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info) +{ + if (!dixRegisterPrivateKey(&dri3_screen_private_key, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!dri3_screen_priv(screen)) { + dri3_screen_priv_ptr screen_priv = calloc(1, sizeof (dri3_screen_priv_rec)); + if (!screen_priv) + return FALSE; + + wrap(screen_priv, screen, CloseScreen, dri3_close_screen); + + screen_priv->info = info; + + dixSetPrivate(&screen->devPrivates, &dri3_screen_private_key, screen_priv); + } + + return TRUE; +} + +void +dri3_extension_init(void) +{ + ExtensionEntry *extension; + int i; + + extension = AddExtension(DRI3_NAME, DRI3NumberEvents, DRI3NumberErrors, + proc_dri3_dispatch, sproc_dri3_dispatch, + NULL, StandardMinorOpcode); + if (!extension) + goto bail; + + dri3_request = extension->base; + + for (i = 0; i < screenInfo.numScreens; i++) { + if (!dri3_screen_init(screenInfo.screens[i], NULL)) + goto bail; + } + return; + +bail: + FatalError("Cannot initialize DRI3 extension"); +} diff --git a/xorg-server/dri3/dri3.h b/xorg-server/dri3/dri3.h new file mode 100644 index 000000000..7774c8757 --- /dev/null +++ b/xorg-server/dri3/dri3.h @@ -0,0 +1,59 @@ +/* + * Copyright © 2013 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 _DRI3_H_ +#define _DRI3_H_ + +#include <X11/extensions/dri3proto.h> +#include <randrstr.h> + +#define DRI3_SCREEN_INFO_VERSION 0 + +typedef int (*dri3_open_proc)(ScreenPtr screen, + RRProviderPtr provider, + int *fd); + +typedef PixmapPtr (*dri3_pixmap_from_fd_proc) (ScreenPtr screen, + int fd, + CARD16 width, + CARD16 height, + CARD16 stride, + CARD8 depth, + CARD8 bpp); + +typedef int (*dri3_fd_from_pixmap_proc) (ScreenPtr screen, + PixmapPtr pixmap, + CARD16 *stride, + CARD32 *size); + +typedef struct dri3_screen_info { + uint32_t version; + + dri3_open_proc open; + dri3_pixmap_from_fd_proc pixmap_from_fd; + dri3_fd_from_pixmap_proc fd_from_pixmap; +} dri3_screen_info_rec, *dri3_screen_info_ptr; + +extern _X_EXPORT Bool +dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info); + +#endif /* _DRI3_H_ */ diff --git a/xorg-server/dri3/dri3_event.c b/xorg-server/dri3/dri3_event.c new file mode 100644 index 000000000..02f0f6579 --- /dev/null +++ b/xorg-server/dri3/dri3_event.c @@ -0,0 +1,163 @@ +/* + * Copyright © 2013 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "dri3_priv.h" + +RESTYPE dri3_event_type; + +static int +dri3_free_event(pointer data, XID id) +{ + dri3_event_ptr dri3_event = (dri3_event_ptr) data; + dri3_window_priv_ptr window_priv = dri3_window_priv(dri3_event->window); + dri3_event_ptr *previous, current; + + for (previous = &window_priv->events; (current = *previous); previous = ¤t->next) { + if (current == dri3_event) { + *previous = dri3_event->next; + break; + } + } + free((pointer) dri3_event); + return 1; + +} + +void +dri3_free_events(WindowPtr window) +{ + dri3_window_priv_ptr window_priv = dri3_window_priv(window); + dri3_event_ptr event; + + if (!window_priv) + return; + + while ((event = window_priv->events)) + FreeResource(event->id, RT_NONE); +} + +static void +dri3_event_swap(xGenericEvent *from, xGenericEvent *to) +{ + *to = *from; + swaps(&to->sequenceNumber); + swapl(&to->length); + swaps(&to->evtype); + switch (from->evtype) { + case DRI3_ConfigureNotify: { + xDRI3ConfigureNotify *c = (xDRI3ConfigureNotify *) to; + + swapl(&c->eid); + swapl(&c->window); + swaps(&c->x); + swaps(&c->y); + swaps(&c->width); + swaps(&c->height); + swaps(&c->off_x); + swaps(&c->off_y); + swaps(&c->pixmap_width); + swaps(&c->pixmap_height); + swapl(&c->pixmap_flags); + break; + } + } +} + +void +dri3_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling) +{ + dri3_window_priv_ptr window_priv = dri3_window_priv(window); + + if (window_priv) { + xDRI3ConfigureNotify cn = { + .type = GenericEvent, + .extension = dri3_request, + .length = (sizeof(xDRI3ConfigureNotify) - 32) >> 2, + .evtype = DRI3_ConfigureNotify, + .eid = 0, + .window = window->drawable.id, + .x = x, + .y = y, + .width = w, + .height = h, + .off_x = 0, + .off_y = 0, + .pixmap_width = w, + .pixmap_height = h, + .pixmap_flags = 0 + }; + dri3_event_ptr event; + dri3_screen_priv_ptr screen_priv = dri3_screen_priv(window->drawable.pScreen); + + if (screen_priv->info && screen_priv->info->driver_config) + screen_priv->info->driver_config(window, &cn); + + for (event = window_priv->events; event; event = event->next) { + if (event->mask & (1 << DRI3ConfigureNotify)) { + cn.eid = event->id; + WriteEventsToClient(event->client, 1, (xEvent *) &cn); + } + } + } +} + +int +dri3_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask) +{ + dri3_window_priv_ptr window_priv = dri3_window_priv(window); + dri3_event_ptr event; + + if (!window_priv) + return BadAlloc; + + event = calloc (1, sizeof (dri3_event_rec)); + if (!event) + return BadAlloc; + + event->client = client; + event->window = window; + event->id = eid; + event->mask = mask; + + event->next = window_priv->events; + window_priv->events = event; + + if (!AddResource(event->id, dri3_event_type, (pointer) event)) + return BadAlloc; + + return Success; +} + +Bool +dri3_event_init(void) +{ + dri3_event_type = CreateNewResourceType(dri3_free_event, "DRI3Event"); + if (!dri3_event_type) + return FALSE; + + GERegisterExtension(dri3_request, dri3_event_swap); + return TRUE; +} diff --git a/xorg-server/dri3/dri3_priv.h b/xorg-server/dri3/dri3_priv.h new file mode 100644 index 000000000..e2fed839b --- /dev/null +++ b/xorg-server/dri3/dri3_priv.h @@ -0,0 +1,80 @@ +/* + * Copyright © 2013 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 _DRI3PRIV_H_ +#define _DRI3PRIV_H_ + +#include <X11/X.h> +#include "scrnintstr.h" +#include "misc.h" +#include "list.h" +#include "windowstr.h" +#include "dixstruct.h" +#include <randrstr.h> +#include "dri3.h" + +extern int dri3_request; + +extern DevPrivateKeyRec dri3_screen_private_key; + +typedef struct dri3_screen_priv { + CloseScreenProcPtr CloseScreen; + ConfigNotifyProcPtr ConfigNotify; + DestroyWindowProcPtr DestroyWindow; + + dri3_screen_info_ptr info; +} dri3_screen_priv_rec, *dri3_screen_priv_ptr; + +#define wrap(priv,real,mem,func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv,real,mem) {\ + real->mem = priv->mem; \ +} + +static inline dri3_screen_priv_ptr +dri3_screen_priv(ScreenPtr screen) +{ + return (dri3_screen_priv_ptr)dixLookupPrivate(&(screen)->devPrivates, &dri3_screen_private_key); +} + +int +proc_dri3_dispatch(ClientPtr client); + +int +sproc_dri3_dispatch(ClientPtr client); + +/* DDX interface */ + +int +dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd); + +int +dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd, + CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp); + +int +dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size); + +#endif /* _DRI3PRIV_H_ */ diff --git a/xorg-server/dri3/dri3_request.c b/xorg-server/dri3/dri3_request.c new file mode 100644 index 000000000..3ebb9d509 --- /dev/null +++ b/xorg-server/dri3/dri3_request.c @@ -0,0 +1,394 @@ +/* + * Copyright © 2013 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "dri3_priv.h" +#include <syncsrv.h> +#include <unistd.h> +#include <xace.h> +#include "../Xext/syncsdk.h" + +static int +proc_dri3_query_version(ClientPtr client) +{ + REQUEST(xDRI3QueryVersionReq); + xDRI3QueryVersionReply rep = { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .majorVersion = DRI3_MAJOR, + .minorVersion = DRI3_MINOR + }; + + REQUEST_SIZE_MATCH(xDRI3QueryVersionReq); + (void) stuff; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.majorVersion); + swapl(&rep.minorVersion); + } + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +static int +proc_dri3_open(ClientPtr client) +{ + REQUEST(xDRI3OpenReq); + xDRI3OpenReply rep = { + .type = X_Reply, + .nfd = 1, + .sequenceNumber = client->sequence, + .length = 0, + }; + RRProviderPtr provider; + DrawablePtr drawable; + ScreenPtr screen; + int fd; + int status; + + REQUEST_SIZE_MATCH(xDRI3OpenReq); + + status = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixReadAccess); + if (status != Success) + return status; + + if (stuff->provider == None) + provider = NULL; + else if (!RRProviderType) { + return BadMatch; + } else { + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + if (drawable->pScreen != provider->pScreen) + return BadMatch; + } + screen = drawable->pScreen; + + status = dri3_open(client, screen, provider, &fd); + 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); + + return Success; +} + +static int +proc_dri3_pixmap_from_buffer(ClientPtr client) +{ + REQUEST(xDRI3PixmapFromBufferReq); + int fd; + DrawablePtr drawable; + PixmapPtr pixmap; + int rc; + + SetReqFds(client, 1); + REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq); + LEGAL_NEW_RESOURCE(stuff->pixmap, client); + rc = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess); + if (rc != Success) { + client->errorValue = stuff->drawable; + return rc; + } + + if (!stuff->width || !stuff->height) { + client->errorValue = 0; + return BadValue; + } + + if (stuff->width > 32767 || stuff->height > 32767) + return BadAlloc; + + if (stuff->depth != 1) { + DepthPtr depth = drawable->pScreen->allowedDepths; + int i; + for (i = 0; i < drawable->pScreen->numDepths; i++, depth++) + if (depth->depth == stuff->depth) + break; + if (i == drawable->pScreen->numDepths) { + client->errorValue = stuff->depth; + return BadValue; + } + } + + fd = ReadFdFromClient(client); + if (fd < 0) + return BadValue; + + rc = dri3_pixmap_from_fd(&pixmap, + drawable->pScreen, fd, + stuff->width, stuff->height, + stuff->stride, stuff->depth, + stuff->bpp); + close (fd); + if (rc != Success) + return rc; + + pixmap->drawable.id = stuff->pixmap; + + /* security creation/labeling check */ + rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP, + pixmap, RT_NONE, NULL, DixCreateAccess); + + if (rc != Success) { + (*drawable->pScreen->DestroyPixmap) (pixmap); + return rc; + } + if (AddResource(stuff->pixmap, RT_PIXMAP, (pointer) pixmap)) + return Success; + + return Success; +} + +static int +proc_dri3_buffer_from_pixmap(ClientPtr client) +{ + REQUEST(xDRI3BufferFromPixmapReq); + xDRI3BufferFromPixmapReply rep = { + .type = X_Reply, + .nfd = 1, + .sequenceNumber = client->sequence, + .length = 0, + }; + int rc; + int fd; + PixmapPtr pixmap; + + REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq); + rc = dixLookupResourceByType((pointer *) &pixmap, stuff->pixmap, RT_PIXMAP, + client, DixWriteAccess); + if (rc != Success) { + client->errorValue = stuff->pixmap; + return rc; + } + + rep.width = pixmap->drawable.width; + rep.height = pixmap->drawable.height; + rep.depth = pixmap->drawable.depth; + rep.bpp = pixmap->drawable.bitsPerPixel; + + rc = dri3_fd_from_pixmap(&fd, pixmap, &rep.stride, &rep.size); + if (rc != Success) + return rc; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.size); + swaps(&rep.width); + swaps(&rep.height); + swaps(&rep.stride); + } + if (WriteFdToClient(client, fd, TRUE) < 0) { + close(fd); + return BadAlloc; + } + + WriteToClient(client, sizeof(rep), &rep); + + return client->noClientException; +} + +static int +proc_dri3_fence_from_fd(ClientPtr client) +{ + REQUEST(xDRI3FenceFromFDReq); + DrawablePtr drawable; + int fd; + int status; + + SetReqFds(client, 1); + REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq); + LEGAL_NEW_RESOURCE(stuff->fence, client); + + status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess); + if (status != Success) + return status; + + fd = ReadFdFromClient(client); + if (fd < 0) + return BadValue; + + status = SyncCreateFenceFromFD(client, drawable, stuff->fence, + fd, stuff->initially_triggered); + + return status; +} + +static int +proc_dri3_fd_from_fence(ClientPtr client) +{ + REQUEST(xDRI3FDFromFenceReq); + xDRI3FDFromFenceReply rep = { + .type = X_Reply, + .nfd = 1, + .sequenceNumber = client->sequence, + .length = 0, + }; + DrawablePtr drawable; + int fd; + int status; + SyncFence *fence; + + REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq); + + status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess); + if (status != Success) + return status; + status = SyncVerifyFence(&fence, stuff->fence, client, DixWriteAccess); + if (status != Success) + return status; + + fd = SyncFDFromFence(client, drawable, fence); + if (fd < 0) + return BadMatch; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + } + if (WriteFdToClient(client, fd, FALSE) < 0) + return BadAlloc; + + WriteToClient(client, sizeof(rep), &rep); + + return client->noClientException; +} + +int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { + proc_dri3_query_version, /* 0 */ + proc_dri3_open, /* 1 */ + proc_dri3_pixmap_from_buffer, /* 2 */ + proc_dri3_buffer_from_pixmap, /* 3 */ + proc_dri3_fence_from_fd, /* 4 */ + proc_dri3_fd_from_fence, /* 5 */ +}; + +int +proc_dri3_dispatch(ClientPtr client) +{ + REQUEST(xReq); + if (stuff->data >= DRI3NumberRequests || !proc_dri3_vector[stuff->data]) + return BadRequest; + return (*proc_dri3_vector[stuff->data]) (client); +} + +static int +sproc_dri3_query_version(ClientPtr client) +{ + REQUEST(xDRI3QueryVersionReq); + + swaps(&stuff->length); + swapl(&stuff->majorVersion); + swapl(&stuff->minorVersion); + return (*proc_dri3_vector[stuff->dri3ReqType]) (client); +} + +static int +sproc_dri3_open(ClientPtr client) +{ + REQUEST(xDRI3OpenReq); + + swaps(&stuff->length); + swapl(&stuff->drawable); + swapl(&stuff->provider); + return (*proc_dri3_vector[stuff->dri3ReqType]) (client); +} + +static int +sproc_dri3_pixmap_from_buffer(ClientPtr client) +{ + REQUEST(xDRI3PixmapFromBufferReq); + + swaps(&stuff->length); + swapl(&stuff->pixmap); + swapl(&stuff->drawable); + swapl(&stuff->size); + swaps(&stuff->width); + swaps(&stuff->height); + swaps(&stuff->stride); + return (*proc_dri3_vector[stuff->dri3ReqType]) (client); +} + +static int +sproc_dri3_buffer_from_pixmap(ClientPtr client) +{ + REQUEST(xDRI3BufferFromPixmapReq); + + swaps(&stuff->length); + swapl(&stuff->pixmap); + return (*proc_dri3_vector[stuff->dri3ReqType]) (client); +} + +static int +sproc_dri3_fence_from_fd(ClientPtr client) +{ + REQUEST(xDRI3FenceFromFDReq); + + swaps(&stuff->length); + swapl(&stuff->drawable); + swapl(&stuff->fence); + return (*proc_dri3_vector[stuff->dri3ReqType]) (client); +} + +static int +sproc_dri3_fd_from_fence(ClientPtr client) +{ + REQUEST(xDRI3FDFromFenceReq); + + swaps(&stuff->length); + swapl(&stuff->drawable); + swapl(&stuff->fence); + return (*proc_dri3_vector[stuff->dri3ReqType]) (client); +} + +int (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { + sproc_dri3_query_version, /* 0 */ + sproc_dri3_open, /* 1 */ + sproc_dri3_pixmap_from_buffer, /* 2 */ + sproc_dri3_buffer_from_pixmap, /* 3 */ + sproc_dri3_fence_from_fd, /* 4 */ + sproc_dri3_fd_from_fence, /* 5 */ +}; + +int +sproc_dri3_dispatch(ClientPtr client) +{ + REQUEST(xReq); + if (stuff->data >= DRI3NumberRequests || !sproc_dri3_vector[stuff->data]) + return BadRequest; + return (*sproc_dri3_vector[stuff->data]) (client); +} diff --git a/xorg-server/dri3/dri3_screen.c b/xorg-server/dri3/dri3_screen.c new file mode 100644 index 000000000..cf2735b8d --- /dev/null +++ b/xorg-server/dri3/dri3_screen.c @@ -0,0 +1,80 @@ +/* + * Copyright © 2013 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "dri3_priv.h" +#include <syncsdk.h> +#include <misync.h> +#include <misyncshm.h> +#include <randrstr.h> + +int +dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd) +{ + dri3_screen_priv_ptr ds = dri3_screen_priv(screen); + dri3_screen_info_ptr info = ds->info; + int rc; + + if (!info || !info->open) + return BadMatch; + + rc = (*info->open) (screen, provider, fd); + if (rc != Success) + return rc; + + return Success; +} + +int +dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd, + CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp) +{ + dri3_screen_priv_ptr ds = dri3_screen_priv(screen); + dri3_screen_info_ptr info = ds->info; + PixmapPtr pixmap; + + pixmap = (*info->pixmap_from_fd) (screen, fd, width, height, stride, depth, bpp); + if (!pixmap) + return BadAlloc; + + *ppixmap = pixmap; + return Success; +} + +int +dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + dri3_screen_priv_ptr ds = dri3_screen_priv(screen); + dri3_screen_info_ptr info = ds->info; + int fd; + + fd = (*info->fd_from_pixmap)(screen, pixmap, stride, size); + if (fd < 0) + return BadAlloc; + *pfd = fd; + return Success; +} + diff --git a/xorg-server/dri3/dri3int.h b/xorg-server/dri3/dri3int.h new file mode 100644 index 000000000..7f53eba45 --- /dev/null +++ b/xorg-server/dri3/dri3int.h @@ -0,0 +1,26 @@ +/* + * Copyright © 2011 Daniel Stone + * + * 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. + * + * Author: Daniel Stone <daniel@fooishbar.org> + */ + +extern Bool DRI2ModuleSetup(void); diff --git a/xorg-server/glx/glxcmds.c b/xorg-server/glx/glxcmds.c index 64ebf9ecd..efa4aecb2 100644 --- a/xorg-server/glx/glxcmds.c +++ b/xorg-server/glx/glxcmds.c @@ -1118,7 +1118,8 @@ DoGetFBConfigs(__GLXclientState * cl, unsigned screen) WRITE_PAIR(GLX_BIND_TO_MIPMAP_TEXTURE_EXT, modes->bindToMipmapTexture); WRITE_PAIR(GLX_BIND_TO_TEXTURE_TARGETS_EXT, modes->bindToTextureTargets); - WRITE_PAIR(GLX_Y_INVERTED_EXT, modes->yInverted); + /* can't report honestly until mesa is fixed */ + WRITE_PAIR(GLX_Y_INVERTED_EXT, GLX_DONT_CARE); if (modes->drawableType & GLX_PBUFFER_BIT) { WRITE_PAIR(GLX_MAX_PBUFFER_WIDTH, modes->maxPbufferWidth); WRITE_PAIR(GLX_MAX_PBUFFER_HEIGHT, modes->maxPbufferHeight); diff --git a/xorg-server/glx/glxdricommon.c b/xorg-server/glx/glxdricommon.c index 48f0bce21..1022c0075 100644 --- a/xorg-server/glx/glxdricommon.c +++ b/xorg-server/glx/glxdricommon.c @@ -178,6 +178,7 @@ createModeFromConfig(const __DRIcoreExtension * core, config->config.visualType = visualType; config->config.renderType = renderType; config->config.drawableType = drawableType; + config->config.yInverted = GL_TRUE; return &config->config; } diff --git a/xorg-server/hw/dmx/dmxextension.c b/xorg-server/hw/dmx/dmxextension.c index d7296ae2d..c6c6a8e6d 100644 --- a/xorg-server/hw/dmx/dmxextension.c +++ b/xorg-server/hw/dmx/dmxextension.c @@ -68,6 +68,9 @@ * _any_ header files. */ extern FontPtr defaultFont; +/* Hack to get Present to build (present requires RandR) */ +RESTYPE RRCrtcType; + /** This routine provides information to the DMX protocol extension * about a particular screen. */ Bool diff --git a/xorg-server/hw/dmx/dmxinit.c b/xorg-server/hw/dmx/dmxinit.c index 65416ed26..bd868a092 100644 --- a/xorg-server/hw/dmx/dmxinit.c +++ b/xorg-server/hw/dmx/dmxinit.c @@ -109,6 +109,8 @@ Bool dmxGLXSyncSwap = FALSE; Bool dmxGLXFinishSwap = FALSE; #endif +RESTYPE RRProviderType = 0; + Bool dmxIgnoreBadFontPaths = FALSE; Bool dmxAddRemoveScreens = FALSE; diff --git a/xorg-server/hw/kdrive/ephyr/hostx.c b/xorg-server/hw/kdrive/ephyr/hostx.c index 5fa33b9db..ee9ae455c 100644 --- a/xorg-server/hw/kdrive/ephyr/hostx.c +++ b/xorg-server/hw/kdrive/ephyr/hostx.c @@ -695,9 +695,6 @@ hostx_screen_init(KdScreenInfo *screen, malloc(scrpriv->ximg->stride * buffer_height); } - *bytes_per_line = scrpriv->ximg->stride; - *bits_per_pixel = scrpriv->ximg->bpp; - if (scrpriv->win_pre_existing == None && !EphyrWantResize) { /* Ask the WM to keep our size static */ xcb_size_hints_t size_hints = {0}; @@ -717,13 +714,21 @@ hostx_screen_init(KdScreenInfo *screen, scrpriv->win_height = height; if (host_depth_matches_server(scrpriv)) { + *bytes_per_line = scrpriv->ximg->stride; + *bits_per_pixel = scrpriv->ximg->bpp; + EPHYR_DBG("Host matches server"); return scrpriv->ximg->data; } else { - EPHYR_DBG("server bpp %i", scrpriv->server_depth >> 3); - scrpriv->fb_data = - malloc(width * buffer_height * (scrpriv->server_depth >> 3)); + int bytes_per_pixel = scrpriv->server_depth >> 3; + int stride = (width * bytes_per_pixel + 0x3) & ~0x3; + + *bytes_per_line = stride; + *bits_per_pixel = scrpriv->server_depth; + + EPHYR_DBG("server bpp %i", bytes_per_pixel); + scrpriv->fb_data = malloc (stride * buffer_height); return scrpriv->fb_data; } } @@ -762,15 +767,14 @@ hostx_paint_rect(KdScreenInfo *screen, if (!host_depth_matches_server(scrpriv)) { int x, y, idx, bytes_per_pixel = (scrpriv->server_depth >> 3); + int stride = (scrpriv->win_width * bytes_per_pixel + 0x3) & ~0x3; unsigned char r, g, b; unsigned long host_pixel; EPHYR_DBG("Unmatched host depth scrpriv=%p\n", scrpriv); for (y = sy; y < sy + height; y++) for (x = sx; x < sx + width; x++) { - idx = - (scrpriv->win_width * y * bytes_per_pixel) + - (x * bytes_per_pixel); + idx = y * stride + x * bytes_per_pixel; switch (scrpriv->server_depth) { case 16: diff --git a/xorg-server/hw/xfree86/Makefile.am b/xorg-server/hw/xfree86/Makefile.am index 59cfb5f6f..eea16a851 100644 --- a/xorg-server/hw/xfree86/Makefile.am +++ b/xorg-server/hw/xfree86/Makefile.am @@ -41,7 +41,7 @@ nodist_Xorg_SOURCES = sdksyms.c AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@ AM_CPPFLAGS = $(XORG_INCS) -I$(srcdir)/parser -I$(top_srcdir)/miext/cw \ -I$(srcdir)/ddc -I$(srcdir)/i2c -I$(srcdir)/modes -I$(srcdir)/ramdac \ - -I$(srcdir)/dri -I$(srcdir)/dri2 + -I$(srcdir)/dri -I$(srcdir)/dri2 -I$(top_srcdir)/dri3 LOCAL_LIBS = \ $(MAIN_LIB) \ @@ -59,6 +59,8 @@ LOCAL_LIBS = \ dixmods/libxorgxkb.la \ $(DRI_LIB) \ $(DRI2_LIB) \ + $(top_builddir)/dri3/libdri3.la \ + $(top_builddir)/miext/sync/libsync.la \ $(top_builddir)/mi/libmi.la \ $(top_builddir)/os/libos.la Xorg_LDADD = \ diff --git a/xorg-server/hw/xfree86/common/xf86Configure.c b/xorg-server/hw/xfree86/common/xf86Configure.c index 6c5e35919..91e8df93d 100644 --- a/xorg-server/hw/xfree86/common/xf86Configure.c +++ b/xorg-server/hw/xfree86/common/xf86Configure.c @@ -123,12 +123,14 @@ xf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData, switch (bus) { #ifdef XSERVER_LIBPCIACCESS case BUS_PCI: + DevToConfig[i].pVideo = busData; xf86PciConfigureNewDev(busData, DevToConfig[i].pVideo, &DevToConfig[i].GDev, &chipset); break; #endif #if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) case BUS_SBUS: + DevToConfig[i].sVideo = busData; xf86SbusConfigureNewDev(busData, DevToConfig[i].sVideo, &DevToConfig[i].GDev); break; diff --git a/xorg-server/hw/xfree86/common/xf86DPMS.c b/xorg-server/hw/xfree86/common/xf86DPMS.c index 3f1e142c7..881cb2773 100644 --- a/xorg-server/hw/xfree86/common/xf86DPMS.c +++ b/xorg-server/hw/xfree86/common/xf86DPMS.c @@ -36,6 +36,7 @@ #include <X11/X.h> #include "os.h" #include "globals.h" +#include "windowstr.h" #include "xf86.h" #include "xf86Priv.h" #ifdef DPMSExtension @@ -159,7 +160,13 @@ DPMSSet(ClientPtr client, int level) return Success; if (level != DPMSModeOn) { - rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverActive); + if (xf86IsUnblank(screenIsSaved)) { + rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverActive); + if (rc != Success) + return rc; + } + } else if (!xf86IsUnblank(screenIsSaved)) { + rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverReset); if (rc != Success) return rc; } diff --git a/xorg-server/hw/xfree86/common/xf86Events.c b/xorg-server/hw/xfree86/common/xf86Events.c index 7a949fd74..d0b14314b 100644 --- a/xorg-server/hw/xfree86/common/xf86Events.c +++ b/xorg-server/hw/xfree86/common/xf86Events.c @@ -116,6 +116,7 @@ typedef struct x_IHRec { InputHandlerProc ihproc; pointer data; Bool enabled; + Bool is_input; struct x_IHRec *next; } IHRec, *IHPtr; @@ -446,8 +447,12 @@ xf86VTSwitch(void) * Keep the order: Disable Device > LeaveVT * EnterVT > EnableDevice */ - for (ih = InputHandlers; ih; ih = ih->next) - xf86DisableInputHandler(ih); + for (ih = InputHandlers; ih; ih = ih->next) { + if (ih->is_input) + xf86DisableInputHandler(ih); + else + xf86DisableGeneralHandler(ih); + } for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next) { if (pInfo->dev) { if (!pInfo->dev->enabled) @@ -496,9 +501,12 @@ xf86VTSwitch(void) pInfo->flags &= ~XI86_DEVICE_DISABLED; pInfo = pInfo->next; } - for (ih = InputHandlers; ih; ih = ih->next) - xf86EnableInputHandler(ih); - + for (ih = InputHandlers; ih; ih = ih->next) { + if (ih->is_input) + xf86EnableInputHandler(ih); + else + xf86EnableGeneralHandler(ih); + } OsReleaseSIGIO(); } @@ -558,9 +566,12 @@ xf86VTSwitch(void) pInfo = pInfo->next; } - for (ih = InputHandlers; ih; ih = ih->next) - xf86EnableInputHandler(ih); - + for (ih = InputHandlers; ih; ih = ih->next) { + if (ih->is_input) + xf86EnableInputHandler(ih); + else + xf86EnableGeneralHandler(ih); + } #ifdef XSERVER_PLATFORM_BUS /* check for any new output devices */ xf86platformVTProbe(); @@ -600,8 +611,10 @@ xf86AddInputHandler(int fd, InputHandlerProc proc, pointer data) { IHPtr ih = addInputHandler(fd, proc, data); - if (ih) + if (ih) { AddEnabledDevice(fd); + ih->is_input = TRUE; + } return ih; } diff --git a/xorg-server/hw/xfree86/common/xf86RandR.c b/xorg-server/hw/xfree86/common/xf86RandR.c index 5606bee4b..2418731dc 100644 --- a/xorg-server/hw/xfree86/common/xf86RandR.c +++ b/xorg-server/hw/xfree86/common/xf86RandR.c @@ -214,13 +214,15 @@ xf86RandRSetMode(ScreenPtr pScreen, */ xf86ReconfigureLayout(); - /* - * Make sure the whole screen is visible - */ - xf86SetViewport(pScreen, pScreen->width, pScreen->height); - xf86SetViewport(pScreen, 0, 0); - if (pRoot && scrp->vtSema) - (*scrp->EnableDisableFBAccess) (scrp, TRUE); + if (scrp->vtSema) { + /* + * Make sure the whole screen is visible + */ + xf86SetViewport (pScreen, pScreen->width, pScreen->height); + xf86SetViewport (pScreen, 0, 0); + if (pRoot) + (*scrp->EnableDisableFBAccess) (scrp, TRUE); + } return ret; } diff --git a/xorg-server/hw/xfree86/modes/xf86Crtc.c b/xorg-server/hw/xfree86/modes/xf86Crtc.c index 35845e875..2a02c8507 100644 --- a/xorg-server/hw/xfree86/modes/xf86Crtc.c +++ b/xorg-server/hw/xfree86/modes/xf86Crtc.c @@ -3045,10 +3045,22 @@ handle_detailed_physical_size(struct detailed_monitor_section if (det_mon->type == DT && det_mon->section.d_timings.h_size != 0 && det_mon->section.d_timings.v_size != 0) { - - p->output->mm_width = det_mon->section.d_timings.h_size; - p->output->mm_height = det_mon->section.d_timings.v_size; - p->ret = TRUE; + /* some sanity checking for aspect ratio: + assume any h / v (or v / h) > 2.4 to be bogus. + This would even include cinemascope */ + if (((det_mon->section.d_timings.h_size * 5) < + (det_mon->section.d_timings.v_size * 12)) && + ((det_mon->section.d_timings.v_size * 5) < + (det_mon->section.d_timings.h_size * 12))) { + p->output->mm_width = det_mon->section.d_timings.h_size; + p->output->mm_height = det_mon->section.d_timings.v_size; + p->ret = TRUE; + } else + xf86DrvMsg(p->output->scrn->scrnIndex, X_WARNING, + "Output %s: Strange aspect ratio (%i/%i), " + "consider adding a quirk\n", p->output->name, + det_mon->section.d_timings.h_size, + det_mon->section.d_timings.v_size); } } diff --git a/xorg-server/hw/xfree86/sdksyms.sh b/xorg-server/hw/xfree86/sdksyms.sh index 48b48b5db..7c9734c07 100644 --- a/xorg-server/hw/xfree86/sdksyms.sh +++ b/xorg-server/hw/xfree86/sdksyms.sh @@ -99,6 +99,7 @@ cat > sdksyms.c << EOF # include "dri2.h" #endif +# include "dri3.h" /* hw/xfree86/vgahw/Makefile.am -- module */ /* diff --git a/xorg-server/hw/xquartz/bundle/Info.plist.cpp b/xorg-server/hw/xquartz/bundle/Info.plist.cpp index b0106c6da..b99e417aa 100644 --- a/xorg-server/hw/xquartz/bundle/Info.plist.cpp +++ b/xorg-server/hw/xquartz/bundle/Info.plist.cpp @@ -19,9 +19,9 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>2.7.4</string> + <string>2.7.6</string> <key>CFBundleVersion</key> - <string>2.7.4</string> + <string>2.7.6</string> <key>CFBundleSignature</key> <string>x11a</string> <key>CSResourcesFileMapped</key> diff --git a/xorg-server/include/dix-config.h.in b/xorg-server/include/dix-config.h.in index a643dfcc8..397ee967a 100644 --- a/xorg-server/include/dix-config.h.in +++ b/xorg-server/include/dix-config.h.in @@ -39,6 +39,9 @@ /* Build DPMS extension */ #undef DPMSExtension +/* Build DRI3 extension */ +#undef DRI3 + /* Build GLX extension */ #undef GLXEXT @@ -252,6 +255,9 @@ /* Internal define for Xinerama */ #undef PANORAMIX +/* Support Present extension */ +#undef PRESENT + /* Overall prefix */ #undef PROJECTROOT diff --git a/xorg-server/include/dixstruct.h b/xorg-server/include/dixstruct.h index 7711cde99..456e63360 100644 --- a/xorg-server/include/dixstruct.h +++ b/xorg-server/include/dixstruct.h @@ -110,8 +110,16 @@ typedef struct _Client { DeviceIntPtr clientPtr; ClientIdPtr clientIds; + int req_fds; } ClientRec; +static inline void +SetReqFds(ClientPtr client, int req_fds) { + if (client->req_fds != 0 && req_fds != client->req_fds) + LogMessage(X_ERROR, "Mismatching number of request fds %d != %d\n", req_fds, client->req_fds); + client->req_fds = req_fds; +} + /* * Scheduling interface */ diff --git a/xorg-server/include/extinit.h b/xorg-server/include/extinit.h index 6d67bf2e5..fa5f29378 100644 --- a/xorg-server/include/extinit.h +++ b/xorg-server/include/extinit.h @@ -176,4 +176,14 @@ extern void XvExtensionInit(void); extern void XvMCExtensionInit(void); #endif +#if defined(DRI3) +#include <X11/extensions/dri3proto.h> +extern void dri3_extension_init(void); +#endif + +#if defined(PRESENT) +#include <X11/extensions/presentproto.h> +#include "presentext.h" +#endif + #endif diff --git a/xorg-server/include/misc.h b/xorg-server/include/misc.h index 0c67f11fe..17de71041 100644 --- a/xorg-server/include/misc.h +++ b/xorg-server/include/misc.h @@ -305,6 +305,35 @@ __builtin_constant_p(int x) } #endif +/* byte swap a 64-bit value */ +static inline void +swap_uint64(uint64_t *x) +{ + char n; + + n = ((char *) x)[0]; + ((char *) x)[0] = ((char *) x)[7]; + ((char *) x)[7] = n; + + n = ((char *) x)[1]; + ((char *) x)[1] = ((char *) x)[6]; + ((char *) x)[6] = n; + + n = ((char *) x)[2]; + ((char *) x)[2] = ((char *) x)[5]; + ((char *) x)[5] = n; + + n = ((char *) x)[3]; + ((char *) x)[3] = ((char *) x)[4]; + ((char *) x)[4] = n; +} + +#define swapll(x) do { \ + if (sizeof(*(x)) != 8) \ + wrong_size(); \ + swap_uint64((uint64_t *)(x)); \ + } while (0) + /* byte swap a 32-bit value */ static inline void swap_uint32(uint32_t * x) diff --git a/xorg-server/include/os.h b/xorg-server/include/os.h index c7108a5d3..11b219845 100644 --- a/xorg-server/include/os.h +++ b/xorg-server/include/os.h @@ -98,6 +98,10 @@ extern _X_EXPORT int WaitForSomething(int * /*pClientsReady */ extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client */ ); +extern _X_EXPORT int ReadFdFromClient(ClientPtr client); + +extern _X_EXPORT int WriteFdToClient(ClientPtr client, int fd, Bool do_close); + extern _X_EXPORT Bool InsertFakeRequest(ClientPtr /*client */ , char * /*data */ , int /*count */ ); @@ -165,6 +169,7 @@ extern void ListenOnOpenFD(int /* fd */ , int /* noxauth */ ); #endif extern _X_EXPORT CARD32 GetTimeInMillis(void); +extern _X_EXPORT CARD64 GetTimeInMicros(void); extern _X_EXPORT void AdjustWaitForDelay(pointer /*waitTime */ , unsigned long /*newdelay */ ); diff --git a/xorg-server/include/regionstr.h b/xorg-server/include/regionstr.h index 805257b3f..4a0725d62 100644 --- a/xorg-server/include/regionstr.h +++ b/xorg-server/include/regionstr.h @@ -213,6 +213,8 @@ extern _X_EXPORT RegionPtr RegionCreate(BoxPtr /*rect */ , extern _X_EXPORT void RegionDestroy(RegionPtr /*pReg */ ); +extern _X_EXPORT RegionPtr RegionDuplicate(RegionPtr /* pOld */); + static inline Bool RegionCopy(RegionPtr dst, RegionPtr src) { diff --git a/xorg-server/include/xorg-config.h.in b/xorg-server/include/xorg-config.h.in index 0df31aeb2..487d7addb 100644 --- a/xorg-server/include/xorg-config.h.in +++ b/xorg-server/include/xorg-config.h.in @@ -142,4 +142,7 @@ /* Define to 1 if you have the `seteuid' function. */ #undef HAVE_SETEUID +/* Support APM/ACPI power management in the server */ +#undef XF86PM + #endif /* _XORG_CONFIG_H_ */ diff --git a/xorg-server/include/xorg-server.h.in b/xorg-server/include/xorg-server.h.in index 81935be5c..1281b3e5e 100644 --- a/xorg-server/include/xorg-server.h.in +++ b/xorg-server/include/xorg-server.h.in @@ -28,6 +28,9 @@ /* Build DPMS extension */ #undef DPMSExtension +/* Build DRI3 extension */ +#undef DRI3 + /* Build GLX extension */ #undef GLXEXT @@ -67,6 +70,9 @@ /* Internal define for Xinerama */ #undef PANORAMIX +/* Support Present extension */ +#undef PRESENT + /* Support RANDR extension */ #undef RANDR diff --git a/xorg-server/mi/miinitext.c b/xorg-server/mi/miinitext.c index 145da38e9..636618282 100644 --- a/xorg-server/mi/miinitext.c +++ b/xorg-server/mi/miinitext.c @@ -287,6 +287,10 @@ static ExtensionModule staticExtensions[] = { #ifdef DPMSExtension {DPMSExtensionInit, DPMSExtensionName, &noDPMSExtension}, #endif + {present_extension_init, PRESENT_NAME, NULL}, +#ifdef DRI3 + {dri3_extension_init, DRI3_NAME, NULL}, +#endif #ifdef RES {ResExtensionInit, XRES_NAME, &noResExtension}, #endif diff --git a/xorg-server/miext/damage/damage.c b/xorg-server/miext/damage/damage.c index cc0299143..173fe5070 100644 --- a/xorg-server/miext/damage/damage.c +++ b/xorg-server/miext/damage/damage.c @@ -382,10 +382,7 @@ damageValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) drawableDamage(pDrawable); DAMAGE_GC_FUNC_PROLOGUE(pGC); (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); - if (pDamage) - pGCPriv->ops = pGC->ops; /* so it's not NULL, so FUNC_EPILOGUE does work */ - else - pGCPriv->ops = NULL; + pGCPriv->ops = pGC->ops; /* just so it's not NULL */ DAMAGE_GC_FUNC_EPILOGUE(pGC); } diff --git a/xorg-server/miext/sync/Makefile.am b/xorg-server/miext/sync/Makefile.am index 9aa1ba5d5..e25ceacb0 100644 --- a/xorg-server/miext/sync/Makefile.am +++ b/xorg-server/miext/sync/Makefile.am @@ -5,10 +5,11 @@ AM_CFLAGS = $(DIX_CFLAGS) AM_CPPFLAGS = if XORG -sdk_HEADERS = misync.h misyncstr.h +sdk_HEADERS = misync.h misyncstr.h misyncshm.h endif libsync_la_SOURCES = \ misync.c \ misync.h \ + misyncshm.c \ misyncstr.h diff --git a/xorg-server/miext/sync/misync.c b/xorg-server/miext/sync/misync.c index b6914d18d..3d03d1b59 100644 --- a/xorg-server/miext/sync/misync.c +++ b/xorg-server/miext/sync/misync.c @@ -29,20 +29,7 @@ #include "misync.h" #include "misyncstr.h" -static DevPrivateKeyRec syncScreenPrivateKeyRec; -static DevPrivateKey syncScreenPrivateKey = &syncScreenPrivateKeyRec; - -#define SYNC_SCREEN_PRIV(pScreen) \ - (SyncScreenPrivPtr) dixLookupPrivate(&pScreen->devPrivates, \ - syncScreenPrivateKey) - -typedef struct _syncScreenPriv { - /* Wrappable sync-specific screen functions */ - SyncScreenFuncsRec funcs; - - /* Wrapped screen functions */ - CloseScreenProcPtr CloseScreen; -} SyncScreenPrivRec, *SyncScreenPrivPtr; +DevPrivateKeyRec miSyncScreenPrivateKey; /* Default implementations of the sync screen functions */ void @@ -62,25 +49,25 @@ miSyncScreenDestroyFence(ScreenPtr pScreen, SyncFence * pFence) } /* Default implementations of the per-object functions */ -static void +void miSyncFenceSetTriggered(SyncFence * pFence) { pFence->triggered = TRUE; } -static void +void miSyncFenceReset(SyncFence * pFence) { pFence->triggered = FALSE; } -static Bool +Bool miSyncFenceCheckTriggered(SyncFence * pFence) { return pFence->triggered; } -static void +void miSyncFenceAddTrigger(SyncTrigger * pTrigger) { (void) pTrigger; @@ -88,7 +75,7 @@ miSyncFenceAddTrigger(SyncTrigger * pTrigger) return; } -static void +void miSyncFenceDeleteTrigger(SyncTrigger * pTrigger) { (void) pTrigger; @@ -182,15 +169,15 @@ miSyncSetup(ScreenPtr pScreen) &miSyncScreenDestroyFence }; - if (!dixPrivateKeyRegistered(syncScreenPrivateKey)) { - if (!dixRegisterPrivateKey(syncScreenPrivateKey, PRIVATE_SCREEN, + if (!dixPrivateKeyRegistered(&miSyncScreenPrivateKey)) { + if (!dixRegisterPrivateKey(&miSyncScreenPrivateKey, PRIVATE_SCREEN, sizeof(SyncScreenPrivRec))) return FALSE; } pScreenPriv = SYNC_SCREEN_PRIV(pScreen); - if (pScreenPriv->funcs.CreateFence) { + if (!pScreenPriv->funcs.CreateFence) { pScreenPriv->funcs = miSyncScreenFuncs; /* Wrap CloseScreen to clean up */ diff --git a/xorg-server/miext/sync/misync.h b/xorg-server/miext/sync/misync.h index deebb82bc..f63ec2b82 100644 --- a/xorg-server/miext/sync/misync.h +++ b/xorg-server/miext/sync/misync.h @@ -76,4 +76,25 @@ extern _X_EXPORT SyncScreenFuncsPtr miSyncGetScreenFuncs(ScreenPtr pScreen); extern _X_EXPORT Bool miSyncSetup(ScreenPtr pScreen); +Bool +miSyncFenceCheckTriggered(SyncFence * pFence); + +void +miSyncFenceSetTriggered(SyncFence * pFence); + +void +miSyncFenceReset(SyncFence * pFence); + +void +miSyncFenceAddTrigger(SyncTrigger * pTrigger); + +void +miSyncFenceDeleteTrigger(SyncTrigger * pTrigger); + +int +miSyncInitFenceFromFD(DrawablePtr pDraw, SyncFence *pFence, int fd, BOOL initially_triggered); + +int +miSyncFDFromFence(DrawablePtr pDraw, SyncFence *pFence); + #endif /* _MISYNC_H_ */ diff --git a/xorg-server/miext/sync/misyncshm.c b/xorg-server/miext/sync/misyncshm.c new file mode 100644 index 000000000..ddd15ae49 --- /dev/null +++ b/xorg-server/miext/sync/misyncshm.c @@ -0,0 +1,176 @@ +/* + * Copyright © 2013 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. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "scrnintstr.h" +#include "misync.h" +#include "misyncstr.h" +#include "misyncshm.h" +#include "pixmapstr.h" +#include <sys/mman.h> +#include <unistd.h> +#include <X11/xshmfence.h> + +static DevPrivateKeyRec syncShmFencePrivateKey; + +typedef struct _SyncShmFencePrivate { + int32_t *fence; + int fd; +} SyncShmFencePrivateRec, *SyncShmFencePrivatePtr; + +#define SYNC_FENCE_PRIV(pFence) \ + (SyncShmFencePrivatePtr) dixLookupPrivate(&pFence->devPrivates, &syncShmFencePrivateKey) + +static void +miSyncShmFenceSetTriggered(SyncFence * pFence) +{ + SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence); + + if (pPriv->fence) + xshmfence_trigger(pPriv->fence); + miSyncFenceSetTriggered(pFence); +} + +static void +miSyncShmFenceReset(SyncFence * pFence) +{ + SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence); + + if (pPriv->fence) + xshmfence_reset(pPriv->fence); + miSyncFenceReset(pFence); +} + +static Bool +miSyncShmFenceCheckTriggered(SyncFence * pFence) +{ + SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence); + + if (pPriv->fence) + return xshmfence_query(pPriv->fence); + else + return miSyncFenceCheckTriggered(pFence); +} + +static void +miSyncShmFenceAddTrigger(SyncTrigger * pTrigger) +{ + miSyncFenceAddTrigger(pTrigger); +} + +static void +miSyncShmFenceDeleteTrigger(SyncTrigger * pTrigger) +{ + miSyncFenceDeleteTrigger(pTrigger); +} + +static const SyncFenceFuncsRec miSyncShmFenceFuncs = { + &miSyncShmFenceSetTriggered, + &miSyncShmFenceReset, + &miSyncShmFenceCheckTriggered, + &miSyncShmFenceAddTrigger, + &miSyncShmFenceDeleteTrigger +}; + +static void +miSyncShmScreenCreateFence(ScreenPtr pScreen, SyncFence * pFence, + Bool initially_triggered) +{ + SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence); + + pPriv->fence = NULL; + miSyncScreenCreateFence(pScreen, pFence, initially_triggered); + pFence->funcs = miSyncShmFenceFuncs; +} + +static void +miSyncShmScreenDestroyFence(ScreenPtr pScreen, SyncFence * pFence) +{ + SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence); + + if (pPriv->fence) { + xshmfence_trigger(pPriv->fence); + xshmfence_unmap_shm(pPriv->fence); + close(pPriv->fd); + } + miSyncScreenDestroyFence(pScreen, pFence); +} + +int +miSyncInitFenceFromFD(DrawablePtr pDraw, SyncFence *pFence, int fd, BOOL initially_triggered) + +{ + SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence); + + miSyncInitFence(pDraw->pScreen, pFence, initially_triggered); + + pPriv->fence = xshmfence_map_shm(fd); + if (pPriv->fence) { + pPriv->fd = fd; + return Success; + } + else + close(fd); + return BadValue; +} + +int +miSyncFDFromFence(DrawablePtr pDraw, SyncFence *pFence) +{ + SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence); + + if (!pPriv->fence) { + pPriv->fd = xshmfence_alloc_shm(); + if (pPriv->fd < 0) + return -1; + pPriv->fence = xshmfence_map_shm(pPriv->fd); + if (!pPriv->fence) { + close (pPriv->fd); + return -1; + } + } + return pPriv->fd; +} + +_X_EXPORT Bool miSyncShmScreenInit(ScreenPtr pScreen) +{ + SyncScreenFuncsPtr funcs; + + if (!miSyncSetup(pScreen)) + return FALSE; + + if (!dixPrivateKeyRegistered(&syncShmFencePrivateKey)) { + if (!dixRegisterPrivateKey(&syncShmFencePrivateKey, PRIVATE_SYNC_FENCE, + sizeof(SyncShmFencePrivateRec))) + return FALSE; + } + + funcs = miSyncGetScreenFuncs(pScreen); + + funcs->CreateFence = miSyncShmScreenCreateFence; + funcs->DestroyFence = miSyncShmScreenDestroyFence; + return TRUE; +} + diff --git a/xorg-server/miext/sync/misyncshm.h b/xorg-server/miext/sync/misyncshm.h new file mode 100644 index 000000000..4edbb50c3 --- /dev/null +++ b/xorg-server/miext/sync/misyncshm.h @@ -0,0 +1,28 @@ +/* + * Copyright © 2013 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 _MISYNCSHM_H_ +#define _MISYNCSYM_H_ + +extern _X_EXPORT Bool miSyncShmScreenInit(ScreenPtr pScreen); + +#endif /* _MISYNCSHM_H_ */ diff --git a/xorg-server/miext/sync/misyncstr.h b/xorg-server/miext/sync/misyncstr.h index e19256fee..b5bf6fd91 100644 --- a/xorg-server/miext/sync/misyncstr.h +++ b/xorg-server/miext/sync/misyncstr.h @@ -29,6 +29,7 @@ #define _MISYNCSTR_H_ #include "dix.h" +#include "scrnintstr.h" #include <X11/extensions/syncconst.h> #define CARD64 XSyncValue /* XXX temporary! need real 64 bit values for Alpha */ @@ -79,4 +80,18 @@ typedef struct _SyncTriggerList { struct _SyncTriggerList *next; } SyncTriggerList; +extern DevPrivateKeyRec miSyncScreenPrivateKey; + +#define SYNC_SCREEN_PRIV(pScreen) \ + (SyncScreenPrivPtr) dixLookupPrivate(&pScreen->devPrivates, \ + &miSyncScreenPrivateKey) + +typedef struct _syncScreenPriv { + /* Wrappable sync-specific screen functions */ + SyncScreenFuncsRec funcs; + + /* Wrapped screen functions */ + CloseScreenProcPtr CloseScreen; +} SyncScreenPrivRec, *SyncScreenPrivPtr; + #endif /* _MISYNCSTR_H_ */ diff --git a/xorg-server/os/backtrace.c b/xorg-server/os/backtrace.c index 426f9b15b..3d1195b86 100644 --- a/xorg-server/os/backtrace.c +++ b/xorg-server/os/backtrace.c @@ -114,14 +114,15 @@ xorg_backtrace(void) void xorg_backtrace(void) { - void *array[64]; + const int BT_SIZE = 64; + void *array[BT_SIZE]; const char *mod; int size, i; Dl_info info; ErrorFSigSafe("\n"); ErrorFSigSafe("Backtrace:\n"); - size = backtrace(array, 64); + size = backtrace(array, BT_SIZE); for (i = 0; i < size; i++) { int rc = dladdr(array[i], &info); diff --git a/xorg-server/os/connection.c b/xorg-server/os/connection.c index 6cd8bcf43..162e1d93e 100644 --- a/xorg-server/os/connection.c +++ b/xorg-server/os/connection.c @@ -923,7 +923,7 @@ ErrorConnMax(XtransConnInfo trans_conn) iov[0].iov_len = sz_xConnSetupPrefix; iov[0].iov_base = (char *) &csp; iov[1].iov_len = csp.lengthReason; - iov[1].iov_base = NOROOM; + iov[1].iov_base = (void *) NOROOM; iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3; iov[2].iov_base = pad; (void) _XSERVTransWritev(trans_conn, iov, 3); diff --git a/xorg-server/os/io.c b/xorg-server/os/io.c index 380036664..a20faa56f 100644 --- a/xorg-server/os/io.c +++ b/xorg-server/os/io.c @@ -259,6 +259,12 @@ ReadRequestFromClient(ClientPtr client) oc->input = oci; } + /* Discard any unused file descriptors */ + while (client->req_fds > 0) { + int req_fd = ReadFdFromClient(client); + if (req_fd >= 0) + close(req_fd); + } /* advance to start of next request */ oci->bufptr += oci->lenLastReq; @@ -485,6 +491,29 @@ ReadRequestFromClient(ClientPtr client) return needed; } +int +ReadFdFromClient(ClientPtr client) +{ + int fd = -1; + + if (client->req_fds > 0) { + OsCommPtr oc = (OsCommPtr) client->osPrivate; + + --client->req_fds; + fd = _XSERVTransRecvFd(oc->trans_conn); + } else + LogMessage(X_ERROR, "Request asks for FD without setting req_fds\n"); + return fd; +} + +int +WriteFdToClient(ClientPtr client, int fd, Bool do_close) +{ + OsCommPtr oc = (OsCommPtr) client->osPrivate; + + return _XSERVTransSendFd(oc->trans_conn, fd, do_close); +} + /***************************************************************** * InsertFakeRequest * Splice a consed up (possibly partial) request in as the next request. diff --git a/xorg-server/os/utils.c b/xorg-server/os/utils.c index 97c3125e6..995f62a37 100644 --- a/xorg-server/os/utils.c +++ b/xorg-server/os/utils.c @@ -430,6 +430,11 @@ GetTimeInMillis(void) { return GetTickCount(); } +CARD64 +GetTimeInMicros(void) +{ + return (CARD64) GetTickCount() * 1000; +} #else CARD32 GetTimeInMillis(void) @@ -460,6 +465,28 @@ GetTimeInMillis(void) X_GETTIMEOFDAY(&tv); return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); } + +CARD64 +GetTimeInMicros(void) +{ + struct timeval tv; +#ifdef MONOTONIC_CLOCK + struct timespec tp; + static clockid_t clockid; + + if (!clockid) { + if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) + clockid = CLOCK_MONOTONIC; + else + clockid = ~0L; + } + if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) + return (CARD64) tp.tv_sec * (CARD64)1000000 + tp.tv_nsec / 1000; +#endif + + X_GETTIMEOFDAY(&tv); + return (CARD64) tv.tv_sec * (CARD64)1000000000 + (CARD64) tv.tv_usec * 1000; +} #endif void diff --git a/xorg-server/os/xstrans.c b/xorg-server/os/xstrans.c index 6348a6511..2bc79e7ae 100644 --- a/xorg-server/os/xstrans.c +++ b/xorg-server/os/xstrans.c @@ -5,9 +5,11 @@ #include <X11/Xfuncproto.h> /* ErrorF is used by xtrans */ +#ifndef HAVE_DIX_CONFIG_H extern _X_EXPORT void ErrorF(const char *f, ...) _X_ATTRIBUTE_PRINTF(1, 2); +#endif #define TRANS_REOPEN #define TRANS_SERVER diff --git a/xorg-server/present/Makefile.am b/xorg-server/present/Makefile.am new file mode 100644 index 000000000..7fea6699f --- /dev/null +++ b/xorg-server/present/Makefile.am @@ -0,0 +1,17 @@ +noinst_LTLIBRARIES = libpresent.la +AM_CFLAGS = \ + -DHAVE_XORG_CONFIG_H \ + @DIX_CFLAGS@ @XORG_CFLAGS@ + +libpresent_la_SOURCES = \ + present.h \ + present.c \ + present_event.c \ + present_fake.c \ + present_fence.c \ + present_notify.c \ + present_priv.h \ + present_request.c \ + present_screen.c + +sdk_HEADERS = present.h presentext.h diff --git a/xorg-server/present/present.c b/xorg-server/present/present.c new file mode 100644 index 000000000..4c97ce40c --- /dev/null +++ b/xorg-server/present/present.c @@ -0,0 +1,775 @@ +/* + * Copyright © 2013 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "present_priv.h" +#include <gcstruct.h> +#include <misync.h> +#include <misyncstr.h> +#ifdef MONOTONIC_CLOCK +#include <time.h> +#endif + +static uint64_t present_event_id; +static struct xorg_list present_exec_queue; +static struct xorg_list present_flip_queue; + +#if 0 +#define DebugPresent(x) ErrorF x +#else +#define DebugPresent(x) +#endif + +/* + * Copies the update region from a pixmap to the target drawable + */ +static void +present_copy_region(DrawablePtr drawable, + PixmapPtr pixmap, + RegionPtr update, + int16_t x_off, + int16_t y_off) +{ + ScreenPtr screen = drawable->pScreen; + GCPtr gc; + + gc = GetScratchGC(drawable->depth, screen); + if (update) { + ChangeGCVal changes[2]; + + changes[0].val = x_off; + changes[1].val = y_off; + ChangeGC(serverClient, gc, + GCClipXOrigin|GCClipYOrigin, + changes); + (*gc->funcs->ChangeClip)(gc, CT_REGION, update, 0); + } + ValidateGC(drawable, gc); + (*gc->ops->CopyArea)(&pixmap->drawable, + drawable, + gc, + 0, 0, + pixmap->drawable.width, pixmap->drawable.height, + x_off, y_off); + if (update) + (*gc->funcs->ChangeClip)(gc, CT_NONE, NULL, 0); + FreeScratchGC(gc); +} + +static Bool +present_check_flip(RRCrtcPtr crtc, + WindowPtr window, + PixmapPtr pixmap, + Bool sync_flip, + RegionPtr valid, + int16_t x_off, + int16_t y_off) +{ + ScreenPtr screen = window->drawable.pScreen; + WindowPtr root = screen->root; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (!screen_priv) + return FALSE; + + if (!screen_priv->info) + return FALSE; + + if (!crtc) + return FALSE; + + /* Check to see if the driver supports flips at all */ + if (!screen_priv->info->flip) + return FALSE; + + /* Can't pend a flip while unflipping */ + if (screen_priv->unflip_event_id) { + return FALSE; + } + + /* Can't have two pending flips at the same time */ + if (screen_priv->flip_pending) { + return FALSE; + } + + /* Make sure the window hasn't been redirected with Composite */ + if (screen->GetWindowPixmap(window) != screen->GetScreenPixmap(screen)) + return FALSE; + + /* Check for full-screen window */ + if (!RegionEqual(&window->clipList, &root->winSize)) { + return FALSE; + } + + /* Source pixmap must align with window exactly */ + if (x_off || y_off) { + return FALSE; + } + + /* Make sure the area marked as valid fills the screen */ + if (valid && !RegionEqual(valid, &root->winSize)) { + return FALSE; + } + + /* Does the window match the pixmap exactly? */ + if (window->drawable.x != 0 || window->drawable.y != 0 || +#ifdef COMPOSITE + window->drawable.x != pixmap->screen_x || window->drawable.y != pixmap->screen_y || +#endif + window->drawable.width != pixmap->drawable.width || + window->drawable.height != pixmap->drawable.height) { + return FALSE; + } + + /* Ask the driver for permission */ + if (screen_priv->info->check_flip) { + if (!(*screen_priv->info->check_flip) (crtc, window, pixmap, sync_flip)) { + return FALSE; + } + } + + return TRUE; +} + +static Bool +present_flip(RRCrtcPtr crtc, + uint64_t event_id, + uint64_t target_msc, + PixmapPtr pixmap, + Bool sync_flip) +{ + ScreenPtr screen = crtc->pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + return (*screen_priv->info->flip) (crtc, event_id, target_msc, pixmap, sync_flip); +} + +static void +present_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_t ust, uint64_t crtc_msc) +{ + int n; + + present_send_complete_notify(vblank->window, kind, mode, vblank->serial, ust, crtc_msc - vblank->msc_offset); + for (n = 0; n < vblank->num_notifies; n++) { + WindowPtr window = vblank->notifies[n].window; + CARD32 serial = vblank->notifies[n].serial; + + if (window) + present_send_complete_notify(window, kind, mode, serial, ust, crtc_msc - vblank->msc_offset); + } +} + +static void +present_pixmap_idle(PixmapPtr pixmap, WindowPtr window, CARD32 serial, struct present_fence *present_fence) +{ + present_fence_set_triggered(present_fence); + present_send_idle_notify(window, serial, pixmap, present_fence); +} + +RRCrtcPtr +present_get_crtc(WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (!screen_priv) + return NULL; + + if (!screen_priv->info) + return NULL; + + return (*screen_priv->info->get_crtc)(window); +} + +uint32_t +present_query_capabilities(RRCrtcPtr crtc) +{ + present_screen_priv_ptr screen_priv; + + if (!crtc) + return 0; + + screen_priv = present_screen_priv(crtc->pScreen); + + if (!screen_priv) + return 0; + + if (!screen_priv->info) + return 0; + + return screen_priv->info->capabilities; +} + +static int +present_get_ust_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t *ust, uint64_t *msc) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (crtc == NULL) + return present_fake_get_ust_msc(screen, ust, msc); + else + return (*screen_priv->info->get_ust_msc)(crtc, ust, msc); +} + +static void +present_flush(WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (!screen_priv) + return; + + if (!screen_priv->info) + return; + + (*screen_priv->info->flush) (window); +} + +static int +present_queue_vblank(ScreenPtr screen, + RRCrtcPtr crtc, + uint64_t event_id, + uint64_t msc) +{ + Bool ret; + + if (crtc == NULL) + ret = present_fake_queue_vblank(screen, event_id, msc); + else + { + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + ret = (*screen_priv->info->queue_vblank) (crtc, event_id, msc); + } + return ret; +} + +static uint64_t +present_window_to_crtc_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t window_msc, uint64_t new_msc) +{ + present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); + + if (crtc != window_priv->crtc) { + uint64_t old_ust, old_msc; + + /* The old CRTC may have been turned off, in which case + * we'll just use whatever previous MSC we'd seen from this CRTC + */ + + if (present_get_ust_msc(window, window_priv->crtc, &old_ust, &old_msc) != Success) + old_msc = window_priv->msc; + + window_priv->msc_offset += new_msc - old_msc; + window_priv->crtc = crtc; + } + + return window_msc + window_priv->msc_offset; +} + +static void +present_flip_idle(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (screen_priv->flip_pixmap) { + present_pixmap_idle(screen_priv->flip_pixmap, screen_priv->flip_window, + screen_priv->flip_serial, screen_priv->flip_idle_fence); + present_fence_destroy(screen_priv->flip_idle_fence); + dixDestroyPixmap(screen_priv->flip_pixmap, screen_priv->flip_pixmap->drawable.id); + screen_priv->flip_crtc = NULL; + screen_priv->flip_window = NULL; + screen_priv->flip_serial = 0; + screen_priv->flip_pixmap = NULL; + screen_priv->flip_idle_fence = NULL; + } +} + +static void +present_unflip(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + assert (!screen_priv->unflip_event_id); + assert (!screen_priv->flip_pending); + + /* Update the screen pixmap with the current flip pixmap contents + */ + if (screen_priv->flip_pixmap) { + present_copy_region(&screen->GetScreenPixmap(screen)->drawable, + screen_priv->flip_pixmap, + NULL, 0, 0); + } + screen_priv->unflip_event_id = ++present_event_id; + DebugPresent(("u %lld\n", screen_priv->unflip_event_id)); + (*screen_priv->info->unflip) (screen, screen_priv->unflip_event_id); +} + +static void +present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc); + +static void +present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) +{ + WindowPtr window = vblank->window; + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + DebugPresent(("\tn %p %8lld: %08lx -> %08lx\n", vblank, vblank->target_msc, + vblank->pixmap ? vblank->pixmap->drawable.id : 0, + vblank->window->drawable.id)); + + assert (vblank == screen_priv->flip_pending); + + present_flip_idle(screen); + + /* Transfer reference for pixmap and fence from vblank to screen_priv */ + screen_priv->flip_crtc = vblank->crtc; + screen_priv->flip_window = vblank->window; + screen_priv->flip_serial = vblank->serial; + screen_priv->flip_pixmap = vblank->pixmap; + screen_priv->flip_idle_fence = vblank->idle_fence; + + vblank->pixmap = NULL; + vblank->idle_fence = NULL; + + screen_priv->flip_pending = NULL; + + if (vblank->abort_flip) + present_unflip(screen); + + if (!vblank->window_destroyed) + present_vblank_notify(vblank, PresentCompleteKindPixmap, PresentCompleteModeFlip, ust, crtc_msc); + present_vblank_destroy(vblank); +} + +void +present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc) +{ + present_vblank_ptr vblank, tmp; + int s; + + xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) { + if (vblank->event_id == event_id) { + xorg_list_del(&vblank->event_queue); + present_execute(vblank, ust, msc); + return; + } + } + xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) { + if (vblank->event_id == event_id) { + xorg_list_del(&vblank->event_queue); + present_flip_notify(vblank, ust, msc); + return; + } + } + + for (s = 0; s < screenInfo.numScreens; s++) { + ScreenPtr screen = screenInfo.screens[s]; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (event_id == screen_priv->unflip_event_id) { + DebugPresent(("\tun %lld\n", event_id)); + screen_priv->unflip_event_id = 0; + present_flip_idle(screen); + } + } +} + +/* + * 'window' is being reconfigured. Check to see if it is involved + * in flipping and clean up as necessary + */ +void +present_check_flip_window (WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + present_window_priv_ptr window_priv = present_window_priv(window); + present_vblank_ptr flip_pending = screen_priv->flip_pending; + present_vblank_ptr vblank; + + /* If this window hasn't ever been used with Present, it can't be + * flipping + */ + if (!window_priv) + return; + + if (screen_priv->unflip_event_id) + return; + + if (flip_pending) { + /* + * Check pending flip + */ + if (flip_pending->window == window) { + if (!present_check_flip(flip_pending->crtc, window, flip_pending->pixmap, + flip_pending->sync_flip, NULL, 0, 0)) + flip_pending->abort_flip = TRUE; + } + } else { + /* + * Check current flip + */ + if (window == screen_priv->flip_window) { + if (!present_check_flip(screen_priv->flip_crtc, window, screen_priv->flip_pixmap, FALSE, NULL, 0, 0)) + present_unflip(screen); + } + } + + /* Now check any queued vblanks */ + xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { + if (vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, FALSE, NULL, 0, 0)) + vblank->flip = FALSE; + } +} + +/* + * Once the required MSC has been reached, execute the pending request. + * + * For requests to actually present something, either blt contents to + * the screen or queue a frame buffer swap. + * + * For requests to just get the current MSC/UST combo, skip that part and + * go straight to event delivery + */ + +static void +present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) +{ + WindowPtr window = vblank->window; + present_screen_priv_ptr screen_priv = present_screen_priv(window->drawable.pScreen); + + if (vblank->wait_fence) { + /* XXX check fence, queue if not ready */ + } + + xorg_list_del(&vblank->event_queue); + if (vblank->pixmap) { + + if (vblank->flip && screen_priv->flip_pending == NULL && !screen_priv->unflip_event_id) { + + DebugPresent(("\tf %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id)); + /* Prepare to flip by removing from the window/screen lists + * and sticking it into the flip_pending field + */ + screen_priv->flip_pending = vblank; + xorg_list_del(&vblank->window_list); + + xorg_list_add(&vblank->event_queue, &present_flip_queue); + /* Try to flip + */ + if (present_flip(vblank->crtc, vblank->event_id, vblank->target_msc, vblank->pixmap, vblank->sync_flip)) + return; + + xorg_list_del(&vblank->event_queue); + /* Oops, flip failed. Clear the flip_pending field + */ + screen_priv->flip_pending = NULL; + vblank->flip = FALSE; + } + DebugPresent(("\tc %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id)); + if (screen_priv->flip_pending) { + + /* Check pending flip + */ + if (window == screen_priv->flip_pending->window) + screen_priv->flip_pending->abort_flip = TRUE; + } else if (!screen_priv->unflip_event_id) { + + /* Check current flip + */ + if (window == screen_priv->flip_window) + present_unflip(window->drawable.pScreen); + } + present_copy_region(&window->drawable, vblank->pixmap, vblank->update, vblank->x_off, vblank->y_off); + + /* present_copy_region sticks the region into a scratch GC, + * which is then freed, freeing the region + */ + vblank->update = NULL; + present_flush(window); + + present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); + } + present_vblank_notify(vblank, vblank->kind, PresentCompleteModeCopy, ust, crtc_msc); + present_vblank_destroy(vblank); +} + +int +present_pixmap(WindowPtr window, + PixmapPtr pixmap, + CARD32 serial, + RegionPtr valid, + RegionPtr update, + int16_t x_off, + int16_t y_off, + RRCrtcPtr target_crtc, + SyncFence *wait_fence, + SyncFence *idle_fence, + uint32_t options, + uint64_t window_msc, + uint64_t divisor, + uint64_t remainder, + present_notify_ptr notifies, + int num_notifies) +{ + uint64_t ust; + uint64_t target_msc; + uint64_t crtc_msc; + int ret; + present_vblank_ptr vblank; + ScreenPtr screen = window->drawable.pScreen; + present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (!window_priv) + return BadAlloc; + + if (!target_crtc) { + /* Update the CRTC if we have a pixmap or we don't have a CRTC + */ + if (!pixmap) + target_crtc = window_priv->crtc; + + if (!target_crtc) + target_crtc = present_get_crtc(window); + } + + present_get_ust_msc(window, target_crtc, &ust, &crtc_msc); + + target_msc = present_window_to_crtc_msc(window, target_crtc, window_msc, crtc_msc); + + /* Stash the current MSC away in case we need it later + */ + window_priv->msc = crtc_msc; + + /* Adjust target_msc to match modulus + */ + if (crtc_msc >= target_msc) { + if (divisor != 0) { + target_msc = crtc_msc - (crtc_msc % divisor) + remainder; + if (target_msc <= crtc_msc) + target_msc += divisor; + } else + target_msc = crtc_msc; + } + + /* + * Look for a matching presentation already on the list and + * don't bother doing the previous one if this one will overwrite it + * in the same frame + */ + + if (!update) { + xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { + + if (!vblank->pixmap) + continue; + + if (vblank->crtc != target_crtc || vblank->target_msc != target_msc) + continue; + + present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); + present_fence_destroy(vblank->idle_fence); + dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id); + + vblank->pixmap = NULL; + vblank->idle_fence = NULL; + } + } + + vblank = calloc (1, sizeof (present_vblank_rec)); + if (!vblank) + return BadAlloc; + + xorg_list_append(&vblank->window_list, &window_priv->vblank); + xorg_list_init(&vblank->event_queue); + + vblank->screen = screen; + vblank->window = window; + vblank->pixmap = pixmap; + vblank->event_id = ++present_event_id; + if (pixmap) { + vblank->kind = PresentCompleteKindPixmap; + pixmap->refcnt++; + } else + vblank->kind = PresentCompleteKindNotifyMSC; + + vblank->serial = serial; + + if (valid) { + vblank->valid = RegionDuplicate(valid); + if (!vblank->valid) + goto no_mem; + } + if (update) { + vblank->update = RegionDuplicate(update); + if (!vblank->update) + goto no_mem; + } + + vblank->x_off = x_off; + vblank->y_off = y_off; + vblank->target_msc = target_msc; + vblank->crtc = target_crtc; + vblank->msc_offset = window_priv->msc_offset; + vblank->notifies = notifies; + vblank->num_notifies = num_notifies; + + if (!screen_priv->info || !(screen_priv->info->capabilities & PresentCapabilityAsync)) + vblank->sync_flip = TRUE; + + if (pixmap && present_check_flip (target_crtc, window, pixmap, vblank->sync_flip, valid, x_off, y_off)) { + vblank->flip = TRUE; + if (vblank->sync_flip) + target_msc--; + } + + if (idle_fence) { + vblank->idle_fence = present_fence_create(idle_fence); + if (!vblank->idle_fence) + goto no_mem; + } + + if (pixmap) + DebugPresent(("q %p %8lld: %08lx -> %08lx (crtc %d)\n", + vblank, target_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id, target_crtc ? 1 : 0)); + + xorg_list_add(&vblank->event_queue, &present_exec_queue); + if (target_msc >= crtc_msc) { + ret = present_queue_vblank(screen, target_crtc, vblank->event_id, target_msc); + if (ret != Success) { + xorg_list_del(&vblank->event_queue); + goto failure; + } + } else + present_execute(vblank, ust, crtc_msc); + + return Success; + +no_mem: + ret = BadAlloc; +failure: + vblank->notifies = NULL; + present_vblank_destroy(vblank); + return ret; +} + +void +present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) +{ + present_vblank_ptr vblank, tmp; + + if (crtc == NULL) + present_fake_abort_vblank(screen, event_id, msc); + else + { + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + (*screen_priv->info->abort_vblank) (crtc, event_id, msc); + } + + xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) { + if (vblank->event_id == event_id) { + xorg_list_del(&vblank->event_queue); + return; + } + } + xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) { + if (vblank->event_id == event_id) { + xorg_list_del(&vblank->event_queue); + return; + } + } +} + +int +present_notify_msc(WindowPtr window, + CARD32 serial, + uint64_t target_msc, + uint64_t divisor, + uint64_t remainder) +{ + return present_pixmap(window, + NULL, + serial, + NULL, NULL, + 0, 0, + NULL, + NULL, NULL, + 0, + target_msc, divisor, remainder, NULL, 0); +} + +void +present_flip_destroy(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + /* XXX this needs to be synchronous for server reset */ + + /* Do the actual cleanup once the flip has been performed by the hardware */ + if (screen_priv->flip_pending) + screen_priv->flip_pending->abort_flip = TRUE; +} + +void +present_vblank_destroy(present_vblank_ptr vblank) +{ + /* Remove vblank from window and screen lists */ + xorg_list_del(&vblank->window_list); + + DebugPresent(("\td %p %8lld: %08lx -> %08lx\n", vblank, vblank->target_msc, + vblank->pixmap ? vblank->pixmap->drawable.id : 0, + vblank->window->drawable.id)); + + /* Drop pixmap reference */ + if (vblank->pixmap) + dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id); + + /* Free regions */ + if (vblank->valid) + RegionDestroy(vblank->valid); + if (vblank->update) + RegionDestroy(vblank->update); + + if (vblank->idle_fence) + present_fence_destroy(vblank->idle_fence); + + if (vblank->notifies) + present_destroy_notifies(vblank->notifies, vblank->num_notifies); + + free(vblank); +} + +Bool +present_init(void) +{ + xorg_list_init(&present_exec_queue); + xorg_list_init(&present_flip_queue); + present_fake_queue_init(); + return TRUE; +} diff --git a/xorg-server/present/present.h b/xorg-server/present/present.h new file mode 100644 index 000000000..6a451fb23 --- /dev/null +++ b/xorg-server/present/present.h @@ -0,0 +1,118 @@ +/* + * Copyright © 2013 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 _PRESENT_H_ +#define _PRESENT_H_ + +#include <X11/extensions/presentproto.h> +#include "randrstr.h" +#include "presentext.h" + +typedef struct present_vblank present_vblank_rec, *present_vblank_ptr; + +/* Return the current CRTC for 'window'. + */ +typedef RRCrtcPtr (*present_get_crtc_ptr) (WindowPtr window); + +/* Return the current ust/msc for 'crtc' + */ +typedef int (*present_get_ust_msc_ptr) (RRCrtcPtr crtc, uint64_t *ust, uint64_t *msc); + +/* Queue callback on 'crtc' for time 'msc'. Call present_event_notify with 'event_id' + * at or after 'msc'. Return false if it didn't happen (which might occur if 'crtc' + * is not currently generating vblanks). + */ +typedef Bool (*present_queue_vblank_ptr) (RRCrtcPtr crtc, + uint64_t event_id, + uint64_t msc); + +/* Abort pending vblank. The extension is no longer interested in + * 'event_id' which was to be notified at 'msc'. If possible, the + * driver is free to de-queue the notification. + */ +typedef void (*present_abort_vblank_ptr) (RRCrtcPtr crtc, uint64_t event_id, uint64_t msc); + +/* Flush pending drawing on 'window' to the hardware. + */ +typedef void (*present_flush_ptr) (WindowPtr window); + +/* Check if 'pixmap' is suitable for flipping to 'window'. + */ +typedef Bool (*present_check_flip_ptr) (RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, Bool sync_flip); + +/* Flip pixmap, return false if it didn't happen. + * + * 'crtc' is to be used for any necessary synchronization. + * + * 'sync_flip' requests that the flip be performed at the next + * vertical blank interval to avoid tearing artifacts. If false, the + * flip should be performed as soon as possible. + * + * present_event_notify should be called with 'event_id' when the flip + * occurs + */ +typedef Bool (*present_flip_ptr) (RRCrtcPtr crtc, + uint64_t event_id, + uint64_t target_msc, + PixmapPtr pixmap, + Bool sync_flip); + +/* "unflip" back to the regular screen scanout buffer + * + * present_event_notify should be called with 'event_id' when the unflip occurs. + */ +typedef void (*present_unflip_ptr) (ScreenPtr screen, + uint64_t event_id); + +#define PRESENT_SCREEN_INFO_VERSION 0 + +typedef struct present_screen_info { + uint32_t version; + + present_get_crtc_ptr get_crtc; + present_get_ust_msc_ptr get_ust_msc; + present_queue_vblank_ptr queue_vblank; + present_abort_vblank_ptr abort_vblank; + present_flush_ptr flush; + uint32_t capabilities; + present_check_flip_ptr check_flip; + present_flip_ptr flip; + present_unflip_ptr unflip; + +} present_screen_info_rec, *present_screen_info_ptr; + +/* + * Called when 'event_id' occurs. 'ust' and 'msc' indicate when the + * event actually happened + */ +extern _X_EXPORT void +present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc); + +/* 'crtc' has been turned off, so any pending events will never occur. + */ +extern _X_EXPORT void +present_event_abandon(RRCrtcPtr crtc); + +extern _X_EXPORT Bool +present_screen_init(ScreenPtr screen, present_screen_info_ptr info); + +#endif /* _PRESENT_H_ */ diff --git a/xorg-server/present/present_event.c b/xorg-server/present/present_event.c new file mode 100644 index 000000000..a30bc8286 --- /dev/null +++ b/xorg-server/present/present_event.c @@ -0,0 +1,239 @@ +/* + * Copyright © 2013 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "present_priv.h" + +#include "present_priv.h" + +RESTYPE present_event_type; + +static int +present_free_event(pointer data, XID id) +{ + present_event_ptr present_event = (present_event_ptr) data; + present_window_priv_ptr window_priv = present_window_priv(present_event->window); + present_event_ptr *previous, current; + + for (previous = &window_priv->events; (current = *previous); previous = ¤t->next) { + if (current == present_event) { + *previous = present_event->next; + break; + } + } + free((pointer) present_event); + return 1; + +} + +void +present_free_events(WindowPtr window) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + present_event_ptr event; + + if (!window_priv) + return; + + while ((event = window_priv->events)) + FreeResource(event->id, RT_NONE); +} + +static void +present_event_swap(xGenericEvent *from, xGenericEvent *to) +{ + *to = *from; + swaps(&to->sequenceNumber); + swapl(&to->length); + swaps(&to->evtype); + switch (from->evtype) { + case PresentConfigureNotify: { + xPresentConfigureNotify *c = (xPresentConfigureNotify *) to; + + swapl(&c->eid); + swapl(&c->window); + swaps(&c->x); + swaps(&c->y); + swaps(&c->width); + swaps(&c->height); + swaps(&c->off_x); + swaps(&c->off_y); + swaps(&c->pixmap_width); + swaps(&c->pixmap_height); + swapl(&c->pixmap_flags); + break; + } + case PresentCompleteNotify: + { + xPresentCompleteNotify *c = (xPresentCompleteNotify *) to; + swapl(&c->eid); + swapl(&c->window); + swapl(&c->serial); + swapll(&c->ust); + swapll(&c->msc); + } + case PresentIdleNotify: + { + xPresentIdleNotify *c = (xPresentIdleNotify *) to; + swapl(&c->eid); + swapl(&c->window); + swapl(&c->serial); + swapl(&c->idle_fence); + } + } +} + +void +present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + + if (window_priv) { + xPresentConfigureNotify cn = { + .type = GenericEvent, + .extension = present_request, + .length = (sizeof(xPresentConfigureNotify) - 32) >> 2, + .evtype = PresentConfigureNotify, + .eid = 0, + .window = window->drawable.id, + .x = x, + .y = y, + .width = w, + .height = h, + .off_x = 0, + .off_y = 0, + .pixmap_width = w, + .pixmap_height = h, + .pixmap_flags = 0 + }; + present_event_ptr event; + + for (event = window_priv->events; event; event = event->next) { + if (event->mask & (1 << PresentConfigureNotify)) { + cn.eid = event->id; + WriteEventsToClient(event->client, 1, (xEvent *) &cn); + } + } + } +} + +void +present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + + if (window_priv) { + xPresentCompleteNotify cn = { + .type = GenericEvent, + .extension = present_request, + .length = (sizeof(xPresentCompleteNotify) - 32) >> 2, + .evtype = PresentCompleteNotify, + .kind = kind, + .mode = mode, + .eid = 0, + .window = window->drawable.id, + .serial = serial, + .ust = ust, + .msc = msc, + }; + present_event_ptr event; + + for (event = window_priv->events; event; event = event->next) { + if (event->mask & PresentCompleteNotifyMask) { + cn.eid = event->id; + WriteEventsToClient(event->client, 1, (xEvent *) &cn); + } + } + } +} + +void +present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, struct present_fence *idle_fence) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + + if (window_priv) { + xPresentIdleNotify in = { + .type = GenericEvent, + .extension = present_request, + .length = (sizeof(xPresentIdleNotify) - 32) >> 2, + .evtype = PresentIdleNotify, + .eid = 0, + .window = window->drawable.id, + .serial = serial, + .pixmap = pixmap->drawable.id, + .idle_fence = present_fence_id(idle_fence) + }; + present_event_ptr event; + + for (event = window_priv->events; event; event = event->next) { + if (event->mask & PresentIdleNotifyMask) { + in.eid = event->id; + WriteEventsToClient(event->client, 1, (xEvent *) &in); + } + } + } +} + +int +present_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask) +{ + present_window_priv_ptr window_priv = present_get_window_priv(window, mask != 0); + present_event_ptr event; + + if (!window_priv) { + if (mask) + return BadAlloc; + return Success; + } + + event = calloc (1, sizeof (present_event_rec)); + if (!event) + return BadAlloc; + + event->client = client; + event->window = window; + event->id = eid; + event->mask = mask; + + event->next = window_priv->events; + window_priv->events = event; + + if (!AddResource(event->id, present_event_type, (pointer) event)) + return BadAlloc; + + return Success; +} + +Bool +present_event_init(void) +{ + present_event_type = CreateNewResourceType(present_free_event, "PresentEvent"); + if (!present_event_type) + return FALSE; + + GERegisterExtension(present_request, present_event_swap); + return TRUE; +} diff --git a/xorg-server/present/present_fake.c b/xorg-server/present/present_fake.c new file mode 100644 index 000000000..a67759254 --- /dev/null +++ b/xorg-server/present/present_fake.c @@ -0,0 +1,140 @@ +/* + * Copyright © 2013 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "present_priv.h" +#include "list.h" + +static struct xorg_list fake_vblank_queue; + +typedef struct present_fake_vblank { + struct xorg_list list; + uint64_t event_id; + OsTimerPtr timer; + ScreenPtr screen; +} present_fake_vblank_rec, *present_fake_vblank_ptr; + +int +present_fake_get_ust_msc(ScreenPtr screen, uint64_t *ust, uint64_t *msc) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + *ust = GetTimeInMicros(); + *msc = *ust / screen_priv->fake_interval; + return Success; +} + +static void +present_fake_notify(ScreenPtr screen, uint64_t event_id) +{ + uint64_t ust, msc; + + present_fake_get_ust_msc(screen, &ust, &msc); + present_event_notify(event_id, ust, msc); +} + +static CARD32 +present_fake_do_timer(OsTimerPtr timer, + CARD32 time, + pointer arg) +{ + present_fake_vblank_ptr fake_vblank = arg; + + present_fake_notify(fake_vblank->screen, fake_vblank->event_id); + xorg_list_del(&fake_vblank->list); + free(fake_vblank); + return 0; +} + +void +present_fake_abort_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc) +{ + present_fake_vblank_ptr fake_vblank, tmp; + + xorg_list_for_each_entry_safe(fake_vblank, tmp, &fake_vblank_queue, list) { + if (fake_vblank->event_id == event_id) { + TimerCancel(fake_vblank->timer); + xorg_list_del(&fake_vblank->list); + free (fake_vblank); + break; + } + } +} + +int +present_fake_queue_vblank(ScreenPtr screen, + uint64_t event_id, + uint64_t msc) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + uint64_t ust = msc * screen_priv->fake_interval; + uint64_t now = GetTimeInMicros(); + INT32 delay = ((int64_t) (ust - now)) / 1000; + present_fake_vblank_ptr fake_vblank; + + if (delay <= 0) { + present_fake_notify(screen, event_id); + return Success; + } + + fake_vblank = calloc (1, sizeof (present_fake_vblank_rec)); + if (!fake_vblank) + return BadAlloc; + + fake_vblank->screen = screen; + fake_vblank->event_id = event_id; + fake_vblank->timer = TimerSet(NULL, 0, delay, present_fake_do_timer, fake_vblank); + if (!fake_vblank->timer) { + free(fake_vblank); + return BadAlloc; + } + + xorg_list_add(&fake_vblank->list, &fake_vblank_queue); + + return Success; +} + +void +present_fake_screen_init(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + /* For screens with hardware vblank support, the fake code + * will be used for off-screen windows and while screens are blanked, + * in which case we want a slow interval here + * + * Otherwise, pretend that the screen runs at 60Hz + */ + if (screen_priv->info && screen_priv->info->get_crtc) + screen_priv->fake_interval = 1000000; + else + screen_priv->fake_interval = 16667; +} + +void +present_fake_queue_init(void) +{ + xorg_list_init(&fake_vblank_queue); +} diff --git a/xorg-server/present/present_fence.c b/xorg-server/present/present_fence.c new file mode 100644 index 000000000..db5efcaad --- /dev/null +++ b/xorg-server/present/present_fence.c @@ -0,0 +1,112 @@ +/* + * Copyright © 2013 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "present_priv.h" +#include <gcstruct.h> +#include <misync.h> +#include <misyncstr.h> + +/* + * Wraps SyncFence objects so we can add a SyncTrigger to find out + * when the SyncFence gets destroyed and clean up appropriately + */ + +struct present_fence { + SyncTrigger trigger; + SyncFence *fence; +}; + +/* + * SyncTrigger callbacks + */ +static Bool +present_fence_sync_check_trigger(SyncTrigger *trigger, XSyncValue oldval) +{ + return FALSE; +} + +static void +present_fence_sync_trigger_fired(SyncTrigger *trigger) +{ +} + +static void +present_fence_sync_counter_destroyed(SyncTrigger *trigger) +{ + struct present_fence *present_fence = container_of(trigger, struct present_fence, trigger); + + present_fence->fence = NULL; +} + +struct present_fence * +present_fence_create(SyncFence *fence) +{ + struct present_fence *present_fence; + + present_fence = calloc (1, sizeof (struct present_fence)); + if (!present_fence) + return NULL; + + present_fence->fence = fence; + present_fence->trigger.pSync = (SyncObject *) fence; + present_fence->trigger.CheckTrigger = present_fence_sync_check_trigger; + present_fence->trigger.TriggerFired = present_fence_sync_trigger_fired; + present_fence->trigger.CounterDestroyed = present_fence_sync_counter_destroyed; + + if (SyncAddTriggerToSyncObject(&present_fence->trigger) != Success) { + free (present_fence); + return NULL; + } + return present_fence; +} + +void +present_fence_destroy(struct present_fence *present_fence) +{ + if (present_fence) { + if (present_fence->fence) + SyncDeleteTriggerFromSyncObject(&present_fence->trigger); + free(present_fence); + } +} + +void +present_fence_set_triggered(struct present_fence *present_fence) +{ + if (present_fence) + if (present_fence->fence) + (*present_fence->fence->funcs.SetTriggered) (present_fence->fence); +} + +XID +present_fence_id(struct present_fence *present_fence) +{ + if (!present_fence) + return None; + if (!present_fence->fence) + return None; + return present_fence->fence->sync.id; +} diff --git a/xorg-server/present/present_notify.c b/xorg-server/present/present_notify.c new file mode 100644 index 000000000..e272e08dc --- /dev/null +++ b/xorg-server/present/present_notify.c @@ -0,0 +1,114 @@ +/* + * Copyright © 2013 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "present_priv.h" + +/* + * Mark all pending notifies for 'window' as invalid when + * the window is destroyed + */ + +void +present_clear_window_notifies(WindowPtr window) +{ + present_notify_ptr notify; + present_window_priv_ptr window_priv = present_window_priv(window); + + if (!window_priv) + return; + + xorg_list_for_each_entry(notify, &window_priv->notifies, window_list) { + notify->window = NULL; + } +} + +/* + * 'notify' is being freed; remove it from the window's notify list + */ + +void +present_free_window_notify(present_notify_ptr notify) +{ + xorg_list_del(¬ify->window_list); +} + +/* + * 'notify' is new; add it to the specified window + */ + +int +present_add_window_notify(present_notify_ptr notify) +{ + WindowPtr window = notify->window; + present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); + + if (!window_priv) + return BadAlloc; + + xorg_list_add(¬ify->window_list, &window_priv->notifies); + return Success; +} + +int +present_create_notifies(ClientPtr client, int num_notifies, xPresentNotify *x_notifies, present_notify_ptr *p_notifies) +{ + present_notify_ptr notifies; + int i; + int added = 0; + int status; + + notifies = calloc (num_notifies, sizeof (present_notify_rec)); + if (!notifies) + return BadAlloc; + + for (i = 0; i < num_notifies; i++) { + status = dixLookupWindow(¬ifies[i].window, x_notifies[i].window, client, DixGetAttrAccess); + if (status != Success) + goto bail; + + notifies[i].serial = x_notifies[i].serial; + status = present_add_window_notify(¬ifies[i]); + if (status != Success) + goto bail; + + added = i; + } + return Success; + +bail: + present_destroy_notifies(notifies, added); + return status; +} + +void +present_destroy_notifies(present_notify_ptr notifies, int num_notifies) +{ + int i; + for (i = 0; i < num_notifies; i++) + present_free_window_notify(¬ifies[i]); + + free(notifies); +} diff --git a/xorg-server/present/present_priv.h b/xorg-server/present/present_priv.h new file mode 100644 index 000000000..a92b62a2d --- /dev/null +++ b/xorg-server/present/present_priv.h @@ -0,0 +1,288 @@ +/* + * Copyright © 2013 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 _PRESENT_PRIV_H_ +#define _PRESENT_PRIV_H_ + +#include <X11/X.h> +#include "scrnintstr.h" +#include "misc.h" +#include "list.h" +#include "windowstr.h" +#include "dixstruct.h" +#include "present.h" +#include <syncsdk.h> +#include <syncsrv.h> +#include <xfixes.h> +#include <randrstr.h> + +extern int present_request; + +extern DevPrivateKeyRec present_screen_private_key; + +typedef struct present_fence *present_fence_ptr; + +typedef struct present_notify present_notify_rec, *present_notify_ptr; + +struct present_notify { + struct xorg_list window_list; + WindowPtr window; + CARD32 serial; +}; + +struct present_vblank { + struct xorg_list window_list; + struct xorg_list event_queue; + ScreenPtr screen; + WindowPtr window; + PixmapPtr pixmap; + RegionPtr valid; + RegionPtr update; + RRCrtcPtr crtc; + uint32_t serial; + int16_t x_off; + int16_t y_off; + CARD16 kind; + uint64_t event_id; + uint64_t target_msc; + uint64_t msc_offset; + present_fence_ptr idle_fence; + present_fence_ptr wait_fence; + present_notify_ptr notifies; + int num_notifies; + Bool flip; + Bool sync_flip; + Bool abort_flip; + + Bool window_destroyed; +}; + +typedef struct present_screen_priv { + CloseScreenProcPtr CloseScreen; + ConfigNotifyProcPtr ConfigNotify; + DestroyWindowProcPtr DestroyWindow; + ClipNotifyProcPtr ClipNotify; + + present_vblank_ptr flip_pending; + uint64_t unflip_event_id; + + uint32_t fake_interval; + + /* Currently active flipped pixmap and fence */ + RRCrtcPtr flip_crtc; + WindowPtr flip_window; + uint32_t flip_serial; + PixmapPtr flip_pixmap; + present_fence_ptr flip_idle_fence; + + present_screen_info_ptr info; +} present_screen_priv_rec, *present_screen_priv_ptr; + +#define wrap(priv,real,mem,func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv,real,mem) {\ + real->mem = priv->mem; \ +} + +static inline present_screen_priv_ptr +present_screen_priv(ScreenPtr screen) +{ + return (present_screen_priv_ptr)dixLookupPrivate(&(screen)->devPrivates, &present_screen_private_key); +} + +/* + * Each window has a list of clients and event masks + */ +typedef struct present_event *present_event_ptr; + +typedef struct present_event { + present_event_ptr next; + ClientPtr client; + WindowPtr window; + XID id; + int mask; +} present_event_rec; + +typedef struct present_window_priv { + present_event_ptr events; + RRCrtcPtr crtc; /* Last reported CRTC from get_ust_msc */ + uint64_t msc_offset; + uint64_t msc; /* Last reported MSC from the current crtc */ + struct xorg_list vblank; + struct xorg_list notifies; +} present_window_priv_rec, *present_window_priv_ptr; + +extern DevPrivateKeyRec present_window_private_key; + +static inline present_window_priv_ptr +present_window_priv(WindowPtr window) +{ + return (present_window_priv_ptr)dixGetPrivate(&(window)->devPrivates, &present_window_private_key); +} + +present_window_priv_ptr +present_get_window_priv(WindowPtr window, Bool create); + +extern RESTYPE present_event_type; + +/* + * present.c + */ +int +present_pixmap(WindowPtr window, + PixmapPtr pixmap, + CARD32 serial, + RegionPtr valid, + RegionPtr update, + int16_t x_off, + int16_t y_off, + RRCrtcPtr target_crtc, + SyncFence *wait_fence, + SyncFence *idle_fence, + uint32_t options, + uint64_t target_msc, + uint64_t divisor, + uint64_t remainder, + present_notify_ptr notifies, + int num_notifies); + +int +present_notify_msc(WindowPtr window, + CARD32 serial, + uint64_t target_msc, + uint64_t divisor, + uint64_t remainder); + +void +present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc); + +void +present_vblank_destroy(present_vblank_ptr vblank); + +void +present_flip_destroy(ScreenPtr screen); + +void +present_check_flip_window(WindowPtr window); + +RRCrtcPtr +present_get_crtc(WindowPtr window); + +uint32_t +present_query_capabilities(RRCrtcPtr crtc); + +Bool +present_init(void); + +/* + * present_event.c + */ + +void +present_free_events(WindowPtr window); + +void +present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling); + +void +present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc); + +void +present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, present_fence_ptr idle_fence); + +int +present_select_input(ClientPtr client, + CARD32 eid, + WindowPtr window, + CARD32 event_mask); + +Bool +present_event_init(void); + +/* + * present_fake.c + */ +int +present_fake_get_ust_msc(ScreenPtr screen, uint64_t *ust, uint64_t *msc); + +int +present_fake_queue_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc); + +void +present_fake_abort_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc); + +void +present_fake_screen_init(ScreenPtr screen); + +void +present_fake_queue_init(void); + +/* + * present_fence.c + */ +struct present_fence * +present_fence_create(SyncFence *sync_fence); + +void +present_fence_destroy(struct present_fence *present_fence); + +void +present_fence_set_triggered(struct present_fence *present_fence); + +XID +present_fence_id(struct present_fence *present_fence); + +/* + * present_notify.c + */ +void +present_clear_window_notifies(WindowPtr window); + +void +present_free_window_notify(present_notify_ptr notify); + +int +present_add_window_notify(present_notify_ptr notify); + +int +present_create_notifies(ClientPtr client, int num_notifies, xPresentNotify *x_notifies, present_notify_ptr *p_notifies); + +void +present_destroy_notifies(present_notify_ptr notifies, int num_notifies); + +/* + * present_request.c + */ +int +proc_present_dispatch(ClientPtr client); + +int +sproc_present_dispatch(ClientPtr client); + +/* + * present_screen.c + */ + +#endif /* _PRESENT_PRIV_H_ */ diff --git a/xorg-server/present/present_request.c b/xorg-server/present/present_request.c new file mode 100644 index 000000000..095fa2daf --- /dev/null +++ b/xorg-server/present/present_request.c @@ -0,0 +1,330 @@ +/* + * Copyright © 2013 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "present_priv.h" +#include "randrstr.h" + +static int +proc_present_query_version(ClientPtr client) +{ + REQUEST(xPresentQueryVersionReq); + xPresentQueryVersionReply rep = { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .majorVersion = PRESENT_MAJOR, + .minorVersion = PRESENT_MINOR + }; + + REQUEST_SIZE_MATCH(xPresentQueryVersionReq); + (void) stuff; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.majorVersion); + swapl(&rep.minorVersion); + } + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +#define VERIFY_FENCE_OR_NONE(fence_ptr, fence_id, client, access) do { \ + if ((fence_id) == None) \ + (fence_ptr) = NULL; \ + else { \ + int __rc__ = SyncVerifyFence(&fence_ptr, fence_id, client, access); \ + if (__rc__ != Success) \ + return __rc__; \ + } \ + } while (0) + +#define VERIFY_CRTC_OR_NONE(crtc_ptr, crtc_id, client, access) do { \ + if ((crtc_id) == None) \ + (crtc_ptr) = NULL; \ + else { \ + VERIFY_RR_CRTC(crtc_id, crtc_ptr, access); \ + } \ + } while (0) + +static int +proc_present_pixmap(ClientPtr client) +{ + REQUEST(xPresentPixmapReq); + WindowPtr window; + PixmapPtr pixmap; + RegionPtr valid = NULL; + RegionPtr update = NULL; + SyncFence *wait_fence; + SyncFence *idle_fence; + RRCrtcPtr target_crtc; + int ret; + int nnotifies; + present_notify_ptr notifies = NULL; + + REQUEST_AT_LEAST_SIZE(xPresentPixmapReq); + ret = dixLookupWindow(&window, stuff->window, client, DixWriteAccess); + if (ret != Success) + return ret; + ret = dixLookupResourceByType((pointer *) &pixmap, stuff->pixmap, RT_PIXMAP, client, DixReadAccess); + if (ret != Success) + return ret; + + if (window->drawable.depth != pixmap->drawable.depth) + return BadMatch; + + VERIFY_REGION_OR_NONE(valid, stuff->valid, client, DixReadAccess); + VERIFY_REGION_OR_NONE(update, stuff->update, client, DixReadAccess); + + VERIFY_CRTC_OR_NONE(target_crtc, stuff->target_crtc, client, DixReadAccess); + + VERIFY_FENCE_OR_NONE(wait_fence, stuff->wait_fence, client, DixReadAccess); + VERIFY_FENCE_OR_NONE(idle_fence, stuff->idle_fence, client, DixWriteAccess); + + if (stuff->options & ~(PresentAllOptions)) { + client->errorValue = stuff->options; + return BadValue; + } + + /* + * Check to see if remainder is sane + */ + if (stuff->divisor == 0) { + if (stuff->remainder != 0) { + client->errorValue = (CARD32) stuff->remainder; + return BadValue; + } + } else { + if (stuff->remainder >= stuff->divisor) { + client->errorValue = (CARD32) stuff->remainder; + return BadValue; + } + } + + nnotifies = (client->req_len << 2) - sizeof (xPresentPixmapReq); + if (nnotifies % sizeof (xPresentNotify)) + return BadLength; + + nnotifies /= sizeof (xPresentNotify); + if (nnotifies) { + ret = present_create_notifies(client, nnotifies, (xPresentNotify *) (stuff + 1), ¬ifies); + if (ret != Success) + return ret; + } + + ret = present_pixmap(window, pixmap, stuff->serial, valid, update, + stuff->x_off, stuff->y_off, target_crtc, + wait_fence, idle_fence, stuff->options, + stuff->target_msc, stuff->divisor, stuff->remainder, notifies, nnotifies); + if (ret != Success) + present_destroy_notifies(notifies, nnotifies); + return ret; +} + +static int +proc_present_notify_msc(ClientPtr client) +{ + REQUEST(xPresentNotifyMSCReq); + WindowPtr window; + int rc; + + REQUEST_SIZE_MATCH(xPresentNotifyMSCReq); + rc = dixLookupWindow(&window, stuff->window, client, DixReadAccess); + if (rc != Success) + return rc; + + /* + * Check to see if remainder is sane + */ + if (stuff->divisor == 0) { + if (stuff->remainder != 0) { + client->errorValue = (CARD32) stuff->remainder; + return BadValue; + } + } else { + if (stuff->remainder >= stuff->divisor) { + client->errorValue = (CARD32) stuff->remainder; + return BadValue; + } + } + + return present_notify_msc(window, stuff->serial, + stuff->target_msc, stuff->divisor, stuff->remainder); +} + +static int +proc_present_select_input (ClientPtr client) +{ + REQUEST(xPresentSelectInputReq); + WindowPtr window; + int rc; + + REQUEST_SIZE_MATCH(xPresentSelectInputReq); + + LEGAL_NEW_RESOURCE(stuff->eid, client); + + rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + if (stuff->eventMask & ~PresentAllEvents) { + client->errorValue = stuff->eventMask; + return BadValue; + } + return present_select_input(client, stuff->eid, window, stuff->eventMask); +} + +static int +proc_present_query_capabilities (ClientPtr client) +{ + REQUEST(xPresentQueryCapabilitiesReq); + xPresentQueryCapabilitiesReply rep = { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + }; + WindowPtr window; + RRCrtcPtr crtc = NULL; + int r; + + r = dixLookupWindow(&window, stuff->target, client, DixGetAttrAccess); + switch (r) { + case Success: + crtc = present_get_crtc(window); + break; + case BadWindow: + VERIFY_RR_CRTC(stuff->target, crtc, DixGetAttrAccess); + break; + default: + return r; + } + + rep.capabilities = present_query_capabilities(crtc); + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.capabilities); + } + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +int (*proc_present_vector[PresentNumberRequests]) (ClientPtr) = { + proc_present_query_version, /* 0 */ + proc_present_pixmap, /* 1 */ + proc_present_notify_msc, /* 2 */ + proc_present_select_input, /* 3 */ + proc_present_query_capabilities, /* 4 */ +}; + +int +proc_present_dispatch(ClientPtr client) +{ + REQUEST(xReq); + if (stuff->data >= PresentNumberRequests || !proc_present_vector[stuff->data]) + return BadRequest; + return (*proc_present_vector[stuff->data]) (client); +} + +static int +sproc_present_query_version(ClientPtr client) +{ + REQUEST(xPresentQueryVersionReq); + + swaps(&stuff->length); + swapl(&stuff->majorVersion); + swapl(&stuff->minorVersion); + return (*proc_present_vector[stuff->presentReqType]) (client); +} + +static int +sproc_present_pixmap(ClientPtr client) +{ + REQUEST(xPresentPixmapReq); + + swaps(&stuff->length); + swapl(&stuff->window); + swapl(&stuff->pixmap); + swapl(&stuff->valid); + swapl(&stuff->update); + swaps(&stuff->x_off); + swaps(&stuff->y_off); + swapll(&stuff->target_msc); + swapll(&stuff->divisor); + swapll(&stuff->remainder); + swapl(&stuff->idle_fence); + return (*proc_present_vector[stuff->presentReqType]) (client); +} + +static int +sproc_present_notify_msc(ClientPtr client) +{ + REQUEST(xPresentNotifyMSCReq); + + swaps(&stuff->length); + swapl(&stuff->window); + swapll(&stuff->target_msc); + swapll(&stuff->divisor); + swapll(&stuff->remainder); + return (*proc_present_vector[stuff->presentReqType]) (client); +} + +static int +sproc_present_select_input (ClientPtr client) +{ + REQUEST(xPresentSelectInputReq); + + swaps(&stuff->length); + swapl(&stuff->window); + swapl(&stuff->eventMask); + return (*proc_present_vector[stuff->presentReqType]) (client); +} + +static int +sproc_present_query_capabilities (ClientPtr client) +{ + REQUEST(xPresentQueryCapabilitiesReq); + swaps(&stuff->length); + swapl(&stuff->target); + return (*proc_present_vector[stuff->presentReqType]) (client); +} + +int (*sproc_present_vector[PresentNumberRequests]) (ClientPtr) = { + sproc_present_query_version, /* 0 */ + sproc_present_pixmap, /* 1 */ + sproc_present_notify_msc, /* 2 */ + sproc_present_select_input, /* 3 */ + sproc_present_query_capabilities, /* 4 */ +}; + +int +sproc_present_dispatch(ClientPtr client) +{ + REQUEST(xReq); + if (stuff->data >= PresentNumberRequests || !sproc_present_vector[stuff->data]) + return BadRequest; + return (*sproc_present_vector[stuff->data]) (client); +} diff --git a/xorg-server/present/present_screen.c b/xorg-server/present/present_screen.c new file mode 100644 index 000000000..50b2b2d23 --- /dev/null +++ b/xorg-server/present/present_screen.c @@ -0,0 +1,231 @@ +/* + * Copyright © 2013 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "present_priv.h" + +int present_request; +DevPrivateKeyRec present_screen_private_key; +DevPrivateKeyRec present_window_private_key; + +/* + * Get a pointer to a present window private, creating if necessary + */ +present_window_priv_ptr +present_get_window_priv(WindowPtr window, Bool create) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + + if (!create || window_priv != NULL) + return window_priv; + window_priv = calloc (1, sizeof (present_window_priv_rec)); + if (!window_priv) + return NULL; + xorg_list_init(&window_priv->vblank); + xorg_list_init(&window_priv->notifies); + dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv); + return window_priv; +} + +/* + * Hook the close screen function to clean up our screen private + */ +static Bool +present_close_screen(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + present_flip_destroy(screen); + + unwrap(screen_priv, screen, CloseScreen); + (*screen->CloseScreen) (screen); + free(screen_priv); + return TRUE; +} + +/* + * Free any queued presentations for this window + */ +static void +present_free_window_vblank(WindowPtr window) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + present_vblank_ptr vblank, tmp; + + xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) { + present_abort_vblank(window->drawable.pScreen, vblank->crtc, vblank->event_id, vblank->target_msc); + present_vblank_destroy(vblank); + } +} + +/* + * Clean up any pending or current flips for this window + */ +static void +present_clear_window_flip(WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + present_vblank_ptr flip_pending = screen_priv->flip_pending; + + if (flip_pending && flip_pending->window == window) { + assert (flip_pending->abort_flip); + flip_pending->window_destroyed = TRUE; + } + if (screen_priv->flip_window == window) + screen_priv->flip_window = NULL; +} + +/* + * Hook the close window function to clean up our window private + */ +static Bool +present_destroy_window(WindowPtr window) +{ + Bool ret; + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + present_window_priv_ptr window_priv = present_window_priv(window); + + if (window_priv) { + present_clear_window_notifies(window); + present_free_events(window); + present_free_window_vblank(window); + present_clear_window_flip(window); + free(window_priv); + } + unwrap(screen_priv, screen, DestroyWindow); + if (screen->DestroyWindow) + ret = screen->DestroyWindow (window); + else + ret = TRUE; + wrap(screen_priv, screen, DestroyWindow, present_destroy_window); + return ret; +} + +/* + * Hook the config notify screen function to deliver present config notify events + */ +static int +present_config_notify(WindowPtr window, + int x, int y, int w, int h, int bw, + WindowPtr sibling) +{ + int ret; + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + present_send_config_notify(window, x, y, w, h, bw, sibling); + + unwrap(screen_priv, screen, ConfigNotify); + if (screen->ConfigNotify) + ret = screen->ConfigNotify (window, x, y, w, h, bw, sibling); + else + ret = 0; + wrap(screen_priv, screen, ConfigNotify, present_config_notify); + return ret; +} + +/* + * Hook the clip notify screen function to un-flip as necessary + */ + +static void +present_clip_notify(WindowPtr window, int dx, int dy) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + present_check_flip_window(window); + unwrap(screen_priv, screen, ClipNotify) + if (screen->ClipNotify) + screen->ClipNotify (window, dx, dy); + wrap(screen_priv, screen, ClipNotify, present_clip_notify); +} + +/* + * Initialize a screen for use with present + */ +int +present_screen_init(ScreenPtr screen, present_screen_info_ptr info) +{ + if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!dixRegisterPrivateKey(&present_window_private_key, PRIVATE_WINDOW, 0)) + return FALSE; + + if (!present_screen_priv(screen)) { + present_screen_priv_ptr screen_priv = calloc(1, sizeof (present_screen_priv_rec)); + if (!screen_priv) + return FALSE; + + wrap(screen_priv, screen, CloseScreen, present_close_screen); + wrap(screen_priv, screen, DestroyWindow, present_destroy_window); + wrap(screen_priv, screen, ConfigNotify, present_config_notify); + wrap(screen_priv, screen, ClipNotify, present_clip_notify); + + screen_priv->info = info; + + dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv); + + present_fake_screen_init(screen); + } + + return TRUE; +} + +/* + * Initialize the present extension + */ +void +present_extension_init(void) +{ + ExtensionEntry *extension; + int i; + + extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors, + proc_present_dispatch, sproc_present_dispatch, + NULL, StandardMinorOpcode); + if (!extension) + goto bail; + + present_request = extension->base; + + if (!present_init()) + goto bail; + + if (!present_event_init()) + goto bail; + + for (i = 0; i < screenInfo.numScreens; i++) { + if (!present_screen_init(screenInfo.screens[i], NULL)) + goto bail; + } + return; + +bail: + FatalError("Cannot initialize Present extension"); +} diff --git a/xorg-server/present/presentext.h b/xorg-server/present/presentext.h new file mode 100644 index 000000000..f177f55dc --- /dev/null +++ b/xorg-server/present/presentext.h @@ -0,0 +1,29 @@ +/* + * Copyright © 2013 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 _PRESENTEXT_H_ +#define _PRESENTEXT_H_ + +extern _X_EXPORT void +present_extension_init(void); + +#endif /* _PRESENTEXT_H_ */ diff --git a/xorg-server/test/Makefile.am b/xorg-server/test/Makefile.am index eff0c9d81..e59c412ee 100644 --- a/xorg-server/test/Makefile.am +++ b/xorg-server/test/Makefile.am @@ -19,7 +19,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/hw/xfree86/parser \ -I$(top_srcdir)/hw/xfree86/ddc \ -I$(top_srcdir)/hw/xfree86/i2c -I$(top_srcdir)/hw/xfree86/modes \ -I$(top_srcdir)/hw/xfree86/ramdac -I$(top_srcdir)/hw/xfree86/dri \ - -I$(top_srcdir)/hw/xfree86/dri2 + -I$(top_srcdir)/hw/xfree86/dri2 -I$(top_srcdir)/dri3 endif TEST_LDADD=libxservertest.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS) $(GLX_SYS_LIBS) @@ -64,6 +64,10 @@ if DRI2 libxservertest_la_LIBADD += $(top_builddir)/hw/xfree86/dri2/libdri2.la endif +if DRI3 +libxservertest_la_LIBADD += $(top_builddir)/dri3/libdri3.la +endif + else nodist_libxservertest_la_SOURCES = \ ddxstubs.c \ @@ -105,6 +109,11 @@ libxservertest_la_LIBADD += \ $(top_builddir)/record/librecord.la endif +if DRI3 +libxservertest_la_LIBADD += \ + $(top_builddir)/dri3/libdri3.la +endif + if XQUARTZ libxservertest_la_LIBADD += \ $(top_builddir)/miext/rootless/librootless.la |