diff --git a/GL/mesa/main/Makefile.am b/GL/mesa/main/Makefile.am index 4d5b0cd4af..64b383dc96 100644 --- a/GL/mesa/main/Makefile.am +++ b/GL/mesa/main/Makefile.am @@ -60,6 +60,7 @@ nodist_libmain_la_SOURCES = accum.c \ light.c \ lines.c \ matrix.c \ + mipmap.c \ mm.c \ occlude.c \ pixel.c \ diff --git a/configure.ac b/configure.ac index 4a848ca840..195211cb97 100644 --- a/configure.ac +++ b/configure.ac @@ -49,7 +49,8 @@ dnl xwin-config.h covers the XWin DDX. AC_CONFIG_HEADERS(include/xwin-config.h) dnl kdrive-config.h covers the kdrive DDX AC_CONFIG_HEADERS(include/kdrive-config.h) - +dnl libdrm now needs 64-bit file offsets +AC_CONFIG_HEADERS(include/libdrm-config.h) AC_PROG_CC AM_PROG_AS @@ -62,6 +63,7 @@ AC_PROG_MAKE_SET PKG_PROG_PKG_CONFIG AC_PROG_LEX AC_PROG_YACC +AC_SYS_LARGEFILE XORG_PROG_RAWCPP AC_HEADER_DIRENT @@ -873,9 +875,46 @@ PKG_CHECK_MODULES([XSERVERLIBS], [$REQUIRED_LIBS]) XSERVER_CFLAGS="${XSERVERCFLAGS_CFLAGS}" XSERVER_LIBS="${XSERVERLIBS_LIBS} ${SYS_LIBS} -lm" -AC_SUBST([XSERVER_LIBS]) AC_SUBST([SYS_LIBS]) +AC_CHECK_FUNCS([clock_gettime], [have_clock_gettime=yes], + [AC_CHECK_LIB([rt], [clock_gettime], [have_clock_gettime=-lrt], + [have_clock_gettime=no])]) + +AC_MSG_CHECKING([for a useful monotonic clock ...]) + +if ! test "x$have_clock_gettime" = xno; then + if ! test "x$have_clock_gettime" = xyes; then + LIBS="$have_clock_gettime" + else + LIBS="" + fi + + AC_RUN_IFELSE([ +#define _POSIX_C_SOURCE 199309L +#include + +int main(int argc, char *argv[]) { + struct timespec tp; + + if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) + return 0; + else + return 1; +} + ], [MONOTONIC_CLOCK=yes], [MONOTONIC_CLOCK=no], + [MONOTONIC_CLOCK="cross compiling"]) +else + MONOTONIC_CLOCK=no +fi + +AC_MSG_RESULT([$MONOTONIC_CLOCK]) + +if test "x$MONOTONIC_CLOCK" = xyes; then + AC_DEFINE(MONOTONIC_CLOCK, 1, [Have monotonic clock from clock_gettime()]) + XSERVER_LIBS="$XSERVER_LIBS $LIBS" +fi + dnl Imake defines SVR4 on SVR4 systems, and many files check for it, so dnl we need to replicate that here until those can all be fixed AC_MSG_CHECKING([if SVR4 needs to be defined]) @@ -890,6 +929,8 @@ 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_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC" AC_DEFINE_UNQUOTED(X_BYTE_ORDER,[$ENDIAN],[Endian order]) +AC_SUBST([XSERVER_LIBS]) + dnl --------------------------------------------------------------------------- dnl DDX section. dnl --------------------------------------------------------------------------- diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am index 79d2ec5c02..64c54f886f 100644 --- a/hw/xfree86/Makefile.am +++ b/hw/xfree86/Makefile.am @@ -103,4 +103,4 @@ relink: rm -f Xorg && $(MAKE) Xorg xorg.conf.example.pre: xorgconf.cpp - cp $< $@ + cp $(srcdir)/xorgconf.cpp $@ diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index 87b8a0b72b..bff9233f87 100644 --- a/hw/xfree86/common/xf86Config.c +++ b/hw/xfree86/common/xf86Config.c @@ -895,7 +895,7 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts) xf86GetOptValBool(FlagOptions, FLAG_ALLOW_CLOSEDOWN_GRABS, &(xf86Info.grabInfo.allowClosedown)); xf86GetOptValBool(FlagOptions, FLAG_IGNORE_ABI, &xf86Info.ignoreABI); - if (&xf86Info.ignoreABI) { + if (xf86Info.ignoreABI) { xf86Msg(X_CONFIG, "Ignoring ABI Version\n"); } diff --git a/hw/xfree86/os-support/drm/xf86drm.c b/hw/xfree86/os-support/drm/xf86drm.c index 214e58ba77..e990e286ba 100644 --- a/hw/xfree86/os-support/drm/xf86drm.c +++ b/hw/xfree86/os-support/drm/xf86drm.c @@ -33,6 +33,7 @@ #ifdef HAVE_XORG_CONFIG_H +#include #include #endif @@ -2305,3 +2306,957 @@ int drmRemoveSIGIOHandler(int fd) return xf86RemoveSIGIOHandler(fd); } + +/* + * Valid flags are + * DRM_FENCE_FLAG_EMIT + * DRM_FENCE_FLAG_SHAREABLE + * DRM_FENCE_MASK_DRIVER + */ + +int drmFenceCreate(int fd, unsigned flags, int class,unsigned type, + drmFence *fence) +{ + drm_fence_arg_t arg; + + memset(&arg, 0, sizeof(arg)); + arg.type = type; + arg.class = class; + arg.op = drm_fence_create; + if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) + return -errno; + fence->handle = arg.handle; + fence->class = arg.class; + fence->type = arg.type; + fence->flags = arg.flags; + fence->signaled = 0; + return 0; +} + +/* + * Valid flags are + * DRM_FENCE_FLAG_SHAREABLE + * DRM_FENCE_MASK_DRIVER + */ + +int drmFenceBuffers(int fd, unsigned flags, drmFence *fence) +{ + drm_fence_arg_t arg; + + memset(&arg, 0, sizeof(arg)); + arg.flags = flags; + arg.op = drm_fence_buffers; + if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) + return -errno; + fence->handle = arg.handle; + fence->class = arg.class; + fence->type = arg.type; + fence->flags = arg.flags; + fence->signaled = 0; + return 0; +} + +int drmFenceDestroy(int fd, const drmFence *fence) +{ + drm_fence_arg_t arg; + + memset(&arg, 0, sizeof(arg)); + arg.handle = fence->handle; + arg.op = drm_fence_destroy; + if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) + return -errno; + return 0; +} + +int drmFenceReference(int fd, unsigned handle, drmFence *fence) +{ + drm_fence_arg_t arg; + + memset(&arg, 0, sizeof(arg)); + arg.handle = handle; + arg.op = drm_fence_reference; + if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) + return -errno; + fence->handle = arg.handle; + fence->class = arg.class; + fence->type = arg.type; + fence->flags = arg.flags; + fence->signaled = arg.signaled; + return 0; +} + +int drmFenceUnreference(int fd, const drmFence *fence) +{ + drm_fence_arg_t arg; + + memset(&arg, 0, sizeof(arg)); + arg.handle = fence->handle; + arg.op = drm_fence_unreference; + if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) + return -errno; + return 0; +} + +int drmFenceFlush(int fd, drmFence *fence, unsigned flush_type) +{ + drm_fence_arg_t arg; + + memset(&arg, 0, sizeof(arg)); + arg.handle = fence->handle; + arg.type = flush_type; + arg.op = drm_fence_flush; + if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) + return -errno; + fence->class = arg.class; + fence->type = arg.type; + fence->signaled = arg.signaled; + return 0; +} + +int drmFenceUpdate(int fd, drmFence *fence) +{ + drm_fence_arg_t arg; + + memset(&arg, 0, sizeof(arg)); + arg.handle = fence->handle; + arg.op = drm_fence_signaled; + if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) + return -errno; + fence->class = arg.class; + fence->type = arg.type; + fence->signaled = arg.signaled; + return 0; +} + +int drmFenceSignaled(int fd, drmFence *fence, unsigned fenceType, + int *signaled) +{ + int + ret; + + if ((fence->flags & DRM_FENCE_FLAG_SHAREABLE) || + ((fenceType & fence->signaled) != fenceType)) { + + ret = drmFenceFlush(fd, fence, fenceType); + if (ret) + return ret; + } + + *signaled = ((fenceType & fence->signaled) == fenceType); + + return 0; +} + +/* + * Valid flags are + * DRM_FENCE_FLAG_SHAREABLE + * DRM_FENCE_MASK_DRIVER + */ + + +int drmFenceEmit(int fd, unsigned flags, drmFence *fence, unsigned emit_type) +{ + drm_fence_arg_t arg; + + memset(&arg, 0, sizeof(arg)); + arg.flags = flags; + arg.handle = fence->handle; + arg.type = emit_type; + arg.op = drm_fence_emit; + if (ioctl(fd, DRM_IOCTL_FENCE, &arg)) + return -errno; + fence->class = arg.class; + fence->type = arg.type; + fence->signaled = arg.signaled; + return 0; +} + +/* + * Valid flags are + * DRM_FENCE_FLAG_WAIT_LAZY + * DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS + */ + +int drmFenceWait(int fd, unsigned flags, drmFence *fence, unsigned flush_type) +{ + drm_fence_arg_t arg; + int ret; + + if (flush_type == 0) { + flush_type = fence->type; + } + + if (!(fence->flags & DRM_FENCE_FLAG_SHAREABLE)) { + if ((flush_type & fence->signaled) == flush_type) { + return 0; + } + } + + memset(&arg, 0, sizeof(arg)); + arg.handle = fence->handle; + arg.type = flush_type; + arg.flags = flags; + arg.op = drm_fence_wait; + do { + ret = ioctl(fd, DRM_IOCTL_FENCE, &arg); + } while (ret != 0 && errno == EAGAIN); + + if (ret) + return -errno; + + fence->class = arg.class; + fence->type = arg.type; + fence->signaled = arg.signaled; + return 0; +} + +static int drmAdjustListNodes(drmBOList *list) +{ + drmBONode *node; + drmMMListHead *l; + int ret = 0; + + while(list->numCurrent < list->numTarget) { + node = (drmBONode *) malloc(sizeof(*node)); + if (!node) { + ret = -ENOMEM; + break; + } + list->numCurrent++; + DRMLISTADD(&node->head, &list->free); + } + + while(list->numCurrent > list->numTarget) { + l = list->free.next; + if (l == &list->free) + break; + DRMLISTDEL(l); + node = DRMLISTENTRY(drmBONode, l, head); + free(node); + list->numCurrent--; + } + return ret; +} + +void drmBOFreeList(drmBOList *list) +{ + drmBONode *node; + drmMMListHead *l; + + l = list->list.next; + while(l != &list->list) { + DRMLISTDEL(l); + node = DRMLISTENTRY(drmBONode, l, head); + free(node); + l = list->free.next; + list->numCurrent--; + list->numOnList--; + } + + l = list->free.next; + while(l != &list->free) { + DRMLISTDEL(l); + node = DRMLISTENTRY(drmBONode, l, head); + free(node); + l = list->free.next; + list->numCurrent--; + } +} + +int drmBOResetList(drmBOList *list) { + + drmMMListHead *l; + int ret; + + ret = drmAdjustListNodes(list); + if (ret) + return ret; + + l = list->list.next; + while(l != &list->list) { + DRMLISTDEL(l); + DRMLISTADD(l, &list->free); + list->numOnList--; + l = list->list.next; + } + return drmAdjustListNodes(list); +} + +static drmBONode *drmAddListItem(drmBOList *list, drmBO *item, + unsigned long arg0, + unsigned long arg1) +{ + drmBONode *node; + drmMMListHead *l; + + l = list->free.next; + if (l == &list->free) { + node = (drmBONode *) malloc(sizeof(*node)); + if (!node) { + return NULL; + } + list->numCurrent++; + } else { + DRMLISTDEL(l); + node = DRMLISTENTRY(drmBONode, l, head); + } + node->buf = item; + node->arg0 = arg0; + node->arg1 = arg1; + DRMLISTADD(&node->head, &list->list); + list->numOnList++; + return node; +} + +void *drmBOListIterator(drmBOList *list) +{ + void *ret = list->list.next; + + if (ret == &list->list) + return NULL; + return ret; +} + +void *drmBOListNext(drmBOList *list, void *iterator) +{ + void *ret; + + drmMMListHead *l = (drmMMListHead *) iterator; + ret = l->next; + if (ret == &list->list) + return NULL; + return ret; +} + +drmBO *drmBOListBuf(void *iterator) +{ + drmBONode *node; + drmMMListHead *l = (drmMMListHead *) iterator; + node = DRMLISTENTRY(drmBONode, l, head); + + return node->buf; +} + + +int drmBOCreateList(int numTarget, drmBOList *list) +{ + DRMINITLISTHEAD(&list->list); + DRMINITLISTHEAD(&list->free); + list->numTarget = numTarget; + list->numCurrent = 0; + list->numOnList = 0; + return drmAdjustListNodes(list); +} + +static void drmBOCopyReply(const drm_bo_arg_reply_t *rep, + drmBO *buf) +{ + buf->handle = rep->handle; + buf->flags = rep->flags; + buf->size = rep->size; + buf->offset = rep->offset; + buf->mapHandle = rep->arg_handle; + buf->mask = rep->mask; + buf->start = rep->buffer_start; + buf->fenceFlags = rep->fence_flags; + buf->replyFlags = rep->rep_flags; + buf->pageAlignment = rep->page_alignment; +} + + + +int drmBOCreate(int fd, unsigned long start, unsigned long size, + unsigned pageAlignment, void *user_buffer, drm_bo_type_t type, + unsigned mask, + unsigned hint, drmBO *buf) +{ + drm_bo_arg_t arg; + drm_bo_arg_request_t *req = &arg.d.req; + drm_bo_arg_reply_t *rep = &arg.d.rep; + int ret; + + memset(buf, 0, sizeof(*buf)); + memset(&arg, 0, sizeof(arg)); + req->mask = mask; + req->hint = hint; + req->size = size; + req->type = type; + req->page_alignment = pageAlignment; + + buf->virtual = NULL; + + switch(type) { + case drm_bo_type_dc: + req->buffer_start = start; + break; + case drm_bo_type_user: + req->buffer_start = (unsigned long) user_buffer; + buf->virtual = user_buffer; + break; + case drm_bo_type_fake: + req->buffer_start = start; + break; + default: + return -EINVAL; + } + req->op = drm_bo_create; + + do { + ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg); + } while (ret != 0 && errno == EAGAIN); + + if (ret) + return -errno; + if (!arg.handled) { + return -EFAULT; + } + if (rep->ret) { + fprintf(stderr, "Error %d\n", rep->ret); + return rep->ret; + } + + drmBOCopyReply(rep, buf); + buf->mapVirtual = NULL; + buf->mapCount = 0; + + return 0; +} + +int drmBODestroy(int fd, drmBO *buf) +{ + drm_bo_arg_t arg; + drm_bo_arg_request_t *req = &arg.d.req; + drm_bo_arg_reply_t *rep = &arg.d.rep; + + if (buf->mapVirtual && (buf->type != drm_bo_type_fake)) { + (void) drmUnmap(buf->mapVirtual, buf->start + buf->size); + buf->mapVirtual = NULL; + buf->virtual = NULL; + } + + memset(&arg, 0, sizeof(arg)); + req->handle = buf->handle; + req->op = drm_bo_destroy; + + if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg)) + return -errno; + if (!arg.handled) { + return -EFAULT; + } + if (rep->ret) { + return rep->ret; + } + + buf->handle = 0; + return 0; +} + +int drmBOReference(int fd, unsigned handle, drmBO *buf) +{ + + drm_bo_arg_t arg; + drm_bo_arg_request_t *req = &arg.d.req; + drm_bo_arg_reply_t *rep = &arg.d.rep; + + memset(&arg, 0, sizeof(arg)); + req->handle = handle; + req->op = drm_bo_reference; + + if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg)) + return -errno; + if (!arg.handled) { + return -EFAULT; + } + if (rep->ret) { + return rep->ret; + } + + drmBOCopyReply(rep, buf); + buf->type = drm_bo_type_dc; + buf->mapVirtual = NULL; + buf->mapCount = 0; + buf->virtual = NULL; + + return 0; +} + +int drmBOUnReference(int fd, drmBO *buf) +{ + drm_bo_arg_t arg; + drm_bo_arg_request_t *req = &arg.d.req; + drm_bo_arg_reply_t *rep = &arg.d.rep; + + + if (buf->mapVirtual && (buf->type != drm_bo_type_fake)) { + (void) munmap(buf->mapVirtual, buf->start + buf->size); + buf->mapVirtual = NULL; + buf->virtual = NULL; + } + + memset(&arg, 0, sizeof(arg)); + req->handle = buf->handle; + req->op = drm_bo_unreference; + + if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg)) + return -errno; + if (!arg.handled) { + return -EFAULT; + } + if (rep->ret) { + return rep->ret; + } + + buf->handle = 0; + return 0; +} + +/* + * Flags can be DRM_BO_FLAG_READ, DRM_BO_FLAG_WRITE or'ed together + * Hint currently be DRM_BO_HINT_DONT_BLOCK, which makes the + * call return an -EBUSY if it can' immediately honor the mapping request. + */ + +int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint, + void **address) +{ + + drm_bo_arg_t arg; + drm_bo_arg_request_t *req = &arg.d.req; + drm_bo_arg_reply_t *rep = &arg.d.rep; + int ret = 0; + + /* + * Make sure we have a virtual address of the buffer. + */ + + if (!buf->virtual && buf->type != drm_bo_type_fake) { + drmAddress virtual; + virtual = mmap(0, buf->size + buf->start, + PROT_READ | PROT_WRITE, MAP_SHARED, + fd, buf->mapHandle); + if (virtual == MAP_FAILED) { + ret = -errno; + } + if (ret) + return ret; + buf->mapVirtual = virtual; + buf->virtual = ((char *) virtual) + buf->start; + } + + memset(&arg, 0, sizeof(arg)); + req->handle = buf->handle; + req->mask = mapFlags; + req->hint = mapHint; + req->op = drm_bo_map; + + /* + * May hang if the buffer object is busy. + * This IOCTL synchronizes the buffer. + */ + + do { + ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg); + } while (ret != 0 && errno == EAGAIN); + + if (ret) + return ret; + if (!arg.handled) + return -EFAULT; + if (rep->ret) + return rep->ret; + + drmBOCopyReply(rep, buf); + buf->mapFlags = mapFlags; + ++buf->mapCount; + *address = buf->virtual; + + return 0; +} + +int drmBOUnmap(int fd, drmBO *buf) +{ + drm_bo_arg_t arg; + drm_bo_arg_request_t *req = &arg.d.req; + drm_bo_arg_reply_t *rep = &arg.d.rep; + + + memset(&arg, 0, sizeof(arg)); + req->handle = buf->handle; + req->op = drm_bo_unmap; + + if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg)) { + return -errno; + } + if (!arg.handled) + return -EFAULT; + if (rep->ret) + return rep->ret; + + return 0; +} + +int drmBOValidate(int fd, drmBO *buf, unsigned flags, unsigned mask, + unsigned hint) +{ + drm_bo_arg_t arg; + drm_bo_arg_request_t *req = &arg.d.req; + drm_bo_arg_reply_t *rep = &arg.d.rep; + int ret = 0; + + memset(&arg, 0, sizeof(arg)); + req->handle = buf->handle; + req->mask = flags; + req->hint = hint; + req->arg_handle = mask; /* Encode mask in the arg_handle field :/ */ + req->op = drm_bo_validate; + + do{ + ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg); + } while (ret && errno == EAGAIN); + + if (ret) + return ret; + if (!arg.handled) + return -EFAULT; + if (rep->ret) + return rep->ret; + + drmBOCopyReply(rep, buf); + return 0; +} + + +int drmBOFence(int fd, drmBO *buf, unsigned flags, unsigned fenceHandle) +{ + drm_bo_arg_t arg; + drm_bo_arg_request_t *req = &arg.d.req; + drm_bo_arg_reply_t *rep = &arg.d.rep; + int ret = 0; + + memset(&arg, 0, sizeof(arg)); + req->handle = buf->handle; + req->mask = flags; + req->arg_handle = fenceHandle; + req->op = drm_bo_validate; + + ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg); + + if (ret) + return ret; + if (!arg.handled) + return -EFAULT; + if (rep->ret) + return rep->ret; + return 0; +} + +int drmBOInfo(int fd, drmBO *buf) +{ + drm_bo_arg_t arg; + drm_bo_arg_request_t *req = &arg.d.req; + drm_bo_arg_reply_t *rep = &arg.d.rep; + int ret = 0; + + memset(&arg, 0, sizeof(arg)); + req->handle = buf->handle; + req->op = drm_bo_info; + + ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg); + + if (ret) + return ret; + if (!arg.handled) + return -EFAULT; + if (rep->ret) + return rep->ret; + drmBOCopyReply(rep, buf); + return 0; +} + +int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint) +{ + drm_bo_arg_t arg; + drm_bo_arg_request_t *req = &arg.d.req; + drm_bo_arg_reply_t *rep = &arg.d.rep; + int ret = 0; + + if ((buf->flags & DRM_BO_FLAG_SHAREABLE) || + (buf->replyFlags & DRM_BO_REP_BUSY)) { + memset(&arg, 0, sizeof(arg)); + req->handle = buf->handle; + req->op = drm_bo_wait_idle; + req->hint = hint; + + do { + ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg); + } while (ret && errno == EAGAIN); + + if (ret) + return ret; + if (!arg.handled) + return -EFAULT; + if (rep->ret) + return rep->ret; + drmBOCopyReply(rep, buf); + } + return 0; +} + +int drmBOBusy(int fd, drmBO *buf, int *busy) +{ + if (!(buf->flags & DRM_BO_FLAG_SHAREABLE) && + !(buf->replyFlags & DRM_BO_REP_BUSY)) { + *busy = 0; + return 0; + } else { + int ret = drmBOInfo(fd, buf); + if (ret) + return ret; + *busy = (buf->replyFlags & DRM_BO_REP_BUSY); + return 0; + } +} + + +int drmAddValidateItem(drmBOList *list, drmBO *buf, unsigned flags, + unsigned mask, + int *newItem) +{ + drmBONode *node, *cur; + drmMMListHead *l; + + *newItem = 0; + cur = NULL; + + for (l = list->list.next; l != &list->list; l = l->next) { + node = DRMLISTENTRY(drmBONode, l, head); + if (node->buf == buf) { + cur = node; + break; + } + } + if (!cur) { + cur = drmAddListItem(list, buf, flags, mask); + if (!cur) { + drmMsg("Out of memory creating validate list node.\n"); + return -ENOMEM; + } + *newItem = 1; + cur->arg0 = flags; + cur->arg1 = mask; + } else { + unsigned memMask = (cur->arg1 | mask) & DRM_BO_MASK_MEM; + unsigned memFlags = cur->arg0 & flags & memMask; + + if (!memFlags) { + drmMsg("Incompatible memory location requests " + "on validate list.\n"); + drmMsg("Previous flag: 0x%08lx, mask: 0x%08lx\n", + cur->arg0, cur->arg1); + drmMsg("Current flag: 0x%08lx, mask: 0x%08lx\n", + flags, mask); + return -EINVAL; + } + if (mask & cur->arg1 & ~DRM_BO_MASK_MEM & (cur->arg0 ^ flags)) { + drmMsg("Incompatible buffer flag requests " + "on validate list.\n"); + drmMsg("Previous flag: 0x%08lx, mask: 0x%08lx\n", + cur->arg0, cur->arg1); + drmMsg("Current flag: 0x%08lx, mask: 0x%08lx\n", + flags, mask); + return -EINVAL; + } + cur->arg1 |= mask; + cur->arg0 = memFlags | ((cur->arg0 | flags) & + cur->arg1 & ~DRM_BO_MASK_MEM); + } + return 0; +} + + +int drmBOValidateList(int fd, drmBOList *list) +{ + + drmBONode *node; + drmMMListHead *l; + drm_bo_arg_t *arg, *first; + drm_bo_arg_request_t *req; + drm_bo_arg_reply_t *rep; + drm_u64_t *prevNext = NULL; + drmBO *buf; + int ret; + + first = NULL; + + for (l = list->list.next; l != &list->list; l = l->next) { + node = DRMLISTENTRY(drmBONode, l, head); + + arg = &node->bo_arg; + req = &arg->d.req; + + if (!first) + first = arg; + + if (prevNext) + *prevNext = (unsigned long) arg; + + memset(arg, 0, sizeof(*arg)); + prevNext = &arg->next; + req->handle = node->buf->handle; + req->op = drm_bo_validate; + req->mask = node->arg0; + req->hint = 0; + req->arg_handle = node->arg1; + } + + if (!first) + return 0; + + do{ + ret = ioctl(fd, DRM_IOCTL_BUFOBJ, first); + } while (ret && errno == EAGAIN); + + + if (ret) + return -errno; + + for (l = list->list.next; l != &list->list; l = l->next) { + node = DRMLISTENTRY(drmBONode, l, head); + arg = &node->bo_arg; + rep = &arg->d.rep; + + if (!arg->handled) { + drmMsg("Unhandled request\n"); + return -EFAULT; + } + if (rep->ret) + return rep->ret; + + buf = node->buf; + drmBOCopyReply(rep, buf); + } + + return 0; +} + + +int drmBOFenceList(int fd, drmBOList *list, unsigned fenceHandle) +{ + + drmBONode *node; + drmMMListHead *l; + drm_bo_arg_t *arg, *first; + drm_bo_arg_request_t *req; + drm_bo_arg_reply_t *rep; + drm_u64_t *prevNext = NULL; + int ret; + + first = NULL; + + for (l = list->list.next; l != &list->list; l = l->next) { + node = DRMLISTENTRY(drmBONode, l, head); + + arg = &node->bo_arg; + req = &arg->d.req; + + if (!first) + first = arg; + + if (prevNext) + *prevNext = (unsigned long) arg; + + memset(arg, 0, sizeof(*arg)); + prevNext = &arg->next; + req->handle = node->buf->handle; + req->op = drm_bo_fence; + req->mask = node->arg0; + req->arg_handle = fenceHandle; + } + + if (!first) + return 0; + + ret = ioctl(fd, DRM_IOCTL_BUFOBJ, first); + + if (ret) + return -errno; + + for (l = list->list.next; l != &list->list; l = l->next) { + node = DRMLISTENTRY(drmBONode, l, head); + + arg = &node->bo_arg; + rep = &arg->d.rep; + + if (!arg->handled) + return -EFAULT; + if (rep->ret) + return rep->ret; + drmBOCopyReply(rep, node->buf); + } + + return 0; +} + +int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize, + unsigned memType) +{ + drm_mm_init_arg_t arg; + + memset(&arg, 0, sizeof(arg)); + arg.req.op = mm_init; + arg.req.p_offset = pOffset; + arg.req.p_size = pSize; + arg.req.mem_type = memType; + + if (ioctl(fd, DRM_IOCTL_MM_INIT, &arg)) + return -errno; + + return 0; +} + +int drmMMTakedown(int fd, unsigned memType) +{ + drm_mm_init_arg_t arg; + + + memset(&arg, 0, sizeof(arg)); + arg.req.op = mm_takedown; + arg.req.mem_type = memType; + + if (ioctl(fd, DRM_IOCTL_MM_INIT, &arg)) + return -errno; + + return 0; +} + +int drmMMLock(int fd, unsigned memType) +{ + drm_mm_init_arg_t arg; + int ret; + + memset(&arg, 0, sizeof(arg)); + arg.req.op = mm_lock; + arg.req.mem_type = memType; + + do{ + ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg); + } while (ret && errno == EAGAIN); + + return ret; +} + +int drmMMUnlock(int fd, unsigned memType) +{ + drm_mm_init_arg_t arg; + int ret; + + memset(&arg, 0, sizeof(arg)); + arg.req.op = mm_unlock; + arg.req.mem_type = memType; + + do{ + ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg); + } while (ret && errno == EAGAIN); + + return ret; +} diff --git a/hw/xfree86/os-support/xf86drm.h b/hw/xfree86/os-support/xf86drm.h index 107670672a..18e4564d12 100644 --- a/hw/xfree86/os-support/xf86drm.h +++ b/hw/xfree86/os-support/xf86drm.h @@ -36,6 +36,7 @@ #define _XF86DRM_H_ #include +#include /* Defaults, if nothing set in xf86config */ #define DRM_DEV_UID 0 diff --git a/hw/xfree86/os-support/xf86mm.h b/hw/xfree86/os-support/xf86mm.h new file mode 100644 index 0000000000..e1a4e3ed9f --- /dev/null +++ b/hw/xfree86/os-support/xf86mm.h @@ -0,0 +1,210 @@ +/************************************************************************** + * + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA. + * All Rights Reserved. + * + * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ + +#ifndef _XF86MM_H_ +#define _XF86MM_H_ +#include +#include "drm.h" + +/* + * Note on multithreaded applications using this interface. + * Libdrm is not threadsafe, so common buffer, TTM, and fence objects need to + * be protected using an external mutex. + * + * Note: Don't protect the following functions, as it may lead to deadlocks: + * drmBOUnmap(), drmFenceBuffers(). + * The kernel is synchronizing and refcounting buffer maps. + * User space only needs to refcount object usage within the same application. + */ + + +/* + * List macros heavily inspired by the Linux kernel + * list handling. No list looping yet. + */ + +typedef struct _drmMMListHead +{ + struct _drmMMListHead *prev; + struct _drmMMListHead *next; +} drmMMListHead; + +#define DRMINITLISTHEAD(__item) \ + do{ \ + (__item)->prev = (__item); \ + (__item)->next = (__item); \ + } while (0) + +#define DRMLISTADD(__item, __list) \ + do { \ + (__item)->prev = (__list); \ + (__item)->next = (__list)->next; \ + (__list)->next->prev = (__item); \ + (__list)->next = (__item); \ + } while (0) + +#define DRMLISTADDTAIL(__item, __list) \ + do { \ + (__item)->next = (__list); \ + (__item)->prev = (__list)->prev; \ + (__list)->prev->next = (__item); \ + (__list)->prev = (__item); \ + } while(0) + +#define DRMLISTDEL(__item) \ + do { \ + (__item)->prev->next = (__item)->next; \ + (__item)->next->prev = (__item)->prev; \ + } while(0) + +#define DRMLISTDELINIT(__item) \ + do { \ + (__item)->prev->next = (__item)->next; \ + (__item)->next->prev = (__item)->prev; \ + (__item)->next = (__item); \ + (__item)->prev = (__item); \ + } while(0) + +#define DRMLISTENTRY(__type, __item, __field) \ + ((__type *)(((char *) (__item)) - offsetof(__type, __field))) + +typedef struct _drmFence{ + unsigned handle; + int class; + unsigned type; + unsigned flags; + unsigned signaled; + unsigned pad[4]; /* for future expansion */ +} drmFence; + +typedef struct _drmBO{ + drm_bo_type_t type; + unsigned handle; + drm_u64_t mapHandle; + unsigned flags; + unsigned mask; + unsigned mapFlags; + unsigned long size; + unsigned long offset; + unsigned long start; + unsigned replyFlags; + unsigned fenceFlags; + unsigned pageAlignment; + void *virtual; + void *mapVirtual; + int mapCount; + unsigned pad[8]; /* for future expansion */ +} drmBO; + + +typedef struct _drmBONode { + drmMMListHead head; + drmBO *buf; + drm_bo_arg_t bo_arg; + unsigned long arg0; + unsigned long arg1; +} drmBONode; + +typedef struct _drmBOList { + unsigned numTarget; + unsigned numCurrent; + unsigned numOnList; + drmMMListHead list; + drmMMListHead free; +} drmBOList; + +/* Fencing */ + +extern int drmFenceCreate(int fd, unsigned flags, int class, + unsigned type, + drmFence *fence); +extern int drmFenceDestroy(int fd, const drmFence *fence); +extern int drmFenceReference(int fd, unsigned handle, drmFence *fence); +extern int drmFenceUnreference(int fd, const drmFence *fence); +extern int drmFenceFlush(int fd, drmFence *fence, unsigned flush_type); +extern int drmFenceSignaled(int fd, drmFence *fence, + unsigned fenceType, int *signaled); +extern int drmFenceWait(int fd, unsigned flags, drmFence *fence, + unsigned flush_type); +extern int drmFenceEmit(int fd, unsigned flags, drmFence *fence, + unsigned emit_type); +extern int drmFenceBuffers(int fd, unsigned flags, drmFence *fence); +extern int drmFenceUpdate(int fd, drmFence *fence); + + +/* + * Buffer object list functions. + */ + +extern void drmBOFreeList(drmBOList *list); +extern int drmBOResetList(drmBOList *list); +extern void *drmBOListIterator(drmBOList *list); +extern void *drmBOListNext(drmBOList *list, void *iterator); +extern drmBO *drmBOListBuf(void *iterator); +extern int drmBOCreateList(int numTarget, drmBOList *list); + +/* + * Buffer object functions. + */ + +extern int drmBOCreate(int fd, unsigned long start, unsigned long size, + unsigned pageAlignment,void *user_buffer, + drm_bo_type_t type, unsigned mask, + unsigned hint, drmBO *buf); +extern int drmBODestroy(int fd, drmBO *buf); +extern int drmBOReference(int fd, unsigned handle, drmBO *buf); +extern int drmBOUnReference(int fd, drmBO *buf); +extern int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint, + void **address); +extern int drmBOUnmap(int fd, drmBO *buf); +extern int drmBOValidate(int fd, drmBO *buf, unsigned flags, unsigned mask, + unsigned hint); +extern int drmBOFence(int fd, drmBO *buf, unsigned flags, unsigned fenceHandle); +extern int drmBOInfo(int fd, drmBO *buf); +extern int drmBOBusy(int fd, drmBO *buf, int *busy); + + +extern int drmAddValidateItem(drmBOList *list, drmBO *buf, unsigned flags, + unsigned mask, + int *newItem); +extern int drmBOValidateList(int fd, drmBOList *list); +extern int drmBOFenceList(int fd, drmBOList *list, unsigned fenceHandle); +extern int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint); + +/* + * Initialization functions. + */ + +extern int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize, + unsigned memType); +extern int drmMMTakedown(int fd, unsigned memType); +extern int drmMMLock(int fd, unsigned memType); +extern int drmMMUnlock(int fd, unsigned memType); + + +#endif diff --git a/include/dix-config.h.in b/include/dix-config.h.in index 65c42e6af6..35700e4602 100644 --- a/include/dix-config.h.in +++ b/include/dix-config.h.in @@ -445,4 +445,7 @@ /* Define to 1 if modules should avoid the libcwrapper */ #undef NO_LIBCWRAPPER +/* Have a monotonic clock from clock_gettime() */ +#undef MONOTONIC_CLOCK + #endif /* _DIX_CONFIG_H_ */ diff --git a/include/libdrm-config.h.in b/include/libdrm-config.h.in new file mode 100644 index 0000000000..286004b961 --- /dev/null +++ b/include/libdrm-config.h.in @@ -0,0 +1,10 @@ +/* + * libdrm-config.h.in: not at all generated. + */ + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + diff --git a/os/WaitFor.c b/os/WaitFor.c index 0457678099..896fdf15db 100644 --- a/os/WaitFor.c +++ b/os/WaitFor.c @@ -119,11 +119,13 @@ mffs(fd_mask mask) struct _OsTimerRec { OsTimerPtr next; CARD32 expires; + CARD32 delta; OsTimerCallback callback; pointer arg; }; static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev); +static void CheckAllTimers(CARD32 now); static OsTimerPtr timers = NULL; /***************** @@ -200,6 +202,11 @@ WaitForSomething(int *pClientsReady) { now = GetTimeInMillis(); timeout = timers->expires - now; + /* time has rewound. reset the timers. */ + if (timeout > timers->delta) { + CheckAllTimers(now); + timeout = timers->expires - now; + } if (timeout < 0) timeout = 0; waittime.tv_sec = timeout / MILLI_PER_SECOND; @@ -426,6 +433,20 @@ ANYSET(FdMask *src) } #endif +/* If time has rewound, re-run every affected timer. + * TimerForce will change timer->next, but it will _generally_ only + * promote timers in the list, meaning that we should still be + * walking every timer. */ +static void +CheckAllTimers(CARD32 now) +{ + OsTimerPtr timer; + + for (timer = timers; timer; timer = timer->next) { + if (timer->expires - now > timer->delta) + TimerForce(timer); + } +} static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev) @@ -467,8 +488,13 @@ TimerSet(OsTimerPtr timer, int flags, CARD32 millis, } if (!millis) return timer; - if (!(flags & TimerAbsolute)) + if (flags & TimerAbsolute) { + timer->delta = millis - now; + } + else { + timer->delta = millis; millis += now; + } timer->expires = millis; timer->callback = func; timer->arg = arg; @@ -481,8 +507,10 @@ TimerSet(OsTimerPtr timer, int flags, CARD32 millis, } for (prev = &timers; *prev && (int) ((*prev)->expires - millis) <= 0; - prev = &(*prev)->next) - ; + prev = &(*prev)->next) { + if ((*prev)->expires - now > (*prev)->delta) + CheckAllTimers(now); + } timer->next = *prev; *prev = timer; return timer; diff --git a/os/utils.c b/os/utils.c index 31ae26a184..7d258a444a 100644 --- a/os/utils.c +++ b/os/utils.c @@ -53,6 +53,19 @@ OR PERFORMANCE OF THIS SOFTWARE. #include #endif +/* The world's most shocking hack, to ensure we get clock_gettime() and + * CLOCK_MONOTONIC. */ +#ifdef _POSIX_C_SOURCE +#define _SAVED_POSIX_C_SOURCE _POSIX_C_SOURCE +#undef _POSIX_C_SOURCE +#endif +#define _POSIX_C_SOURCE 199309L +#include +#undef _POSIX_C_SOURCE +#ifdef _SAVED_POSIX_C_SOURCE +#define _POSIX_C_SOURCE _SAVED_POSIX_C_SOURCE +#endif + #ifdef __CYGWIN__ #include #include @@ -92,7 +105,6 @@ OR PERFORMANCE OF THIS SOFTWARE. #if !defined(SYSV) && !defined(WIN32) && !defined(Lynx) && !defined(QNX4) #include #endif -#include #include #include /* for isspace */ #include @@ -535,10 +547,16 @@ GiveUp(int sig) _X_EXPORT CARD32 GetTimeInMillis(void) { - struct timeval tp; + struct timeval tv; - X_GETTIMEOFDAY(&tp); - return(tp.tv_sec * 1000) + (tp.tv_usec / 1000); +#ifdef MONOTONIC_CLOCK + struct timespec tp; + if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) + return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000); +#endif + + X_GETTIMEOFDAY(&tv); + return(tv.tv_sec * 1000) + (tv.tv_usec / 1000); } _X_EXPORT void