Module Name:    xsrc
Committed By:   mrg
Date:           Thu Jan 10 08:59:43 UTC 2019

Modified Files:
        xsrc/external/mit/libdrm/dist: xf86atomic.h xf86drm.c xf86drmMode.c
        xsrc/external/mit/libdrm/dist/include/drm: drm.h i915_drm.h
        xsrc/external/mit/libdrm/dist/intel: intel_bufmgr_gem.c
        xsrc/external/mit/libdrm/dist/radeon: radeon_bo_gem.c radeon_cs_gem.c
            radeon_surface.c
        xsrc/external/mit/libdrm/dist/tests/modetest: modetest.c
Removed Files:
        xsrc/external/mit/libdrm/dist/amdgpu: util_hash.c util_hash.h
            util_hash_table.c util_hash_table.h
        xsrc/external/mit/libdrm/dist/freedreno/msm: msm_drm.h

Log Message:
merge libdrm 2.4.96.


To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 xsrc/external/mit/libdrm/dist/xf86atomic.h
cvs rdiff -u -r1.21 -r1.22 xsrc/external/mit/libdrm/dist/xf86drm.c
cvs rdiff -u -r1.13 -r1.14 xsrc/external/mit/libdrm/dist/xf86drmMode.c
cvs rdiff -u -r1.1.1.1 -r0 xsrc/external/mit/libdrm/dist/amdgpu/util_hash.c \
    xsrc/external/mit/libdrm/dist/amdgpu/util_hash.h \
    xsrc/external/mit/libdrm/dist/amdgpu/util_hash_table.c \
    xsrc/external/mit/libdrm/dist/amdgpu/util_hash_table.h
cvs rdiff -u -r1.1.1.6 -r0 \
    xsrc/external/mit/libdrm/dist/freedreno/msm/msm_drm.h
cvs rdiff -u -r1.10 -r1.11 xsrc/external/mit/libdrm/dist/include/drm/drm.h
cvs rdiff -u -r1.5 -r1.6 xsrc/external/mit/libdrm/dist/include/drm/i915_drm.h
cvs rdiff -u -r1.15 -r1.16 \
    xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c
cvs rdiff -u -r1.7 -r1.8 xsrc/external/mit/libdrm/dist/radeon/radeon_bo_gem.c \
    xsrc/external/mit/libdrm/dist/radeon/radeon_cs_gem.c
cvs rdiff -u -r1.10 -r1.11 \
    xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c
cvs rdiff -u -r1.11 -r1.12 \
    xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: xsrc/external/mit/libdrm/dist/xf86atomic.h
diff -u xsrc/external/mit/libdrm/dist/xf86atomic.h:1.10 xsrc/external/mit/libdrm/dist/xf86atomic.h:1.11
--- xsrc/external/mit/libdrm/dist/xf86atomic.h:1.10	Wed Mar 14 07:19:26 2018
+++ xsrc/external/mit/libdrm/dist/xf86atomic.h	Thu Jan 10 08:59:43 2019
@@ -34,10 +34,6 @@
 #ifndef LIBDRM_ATOMICS_H
 #define LIBDRM_ATOMICS_H
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #if HAVE_LIBDRM_ATOMIC_PRIMITIVES
 
 #define HAS_ATOMIC_OPS 1

Index: xsrc/external/mit/libdrm/dist/xf86drm.c
diff -u xsrc/external/mit/libdrm/dist/xf86drm.c:1.21 xsrc/external/mit/libdrm/dist/xf86drm.c:1.22
--- xsrc/external/mit/libdrm/dist/xf86drm.c:1.21	Fri Sep 21 18:33:08 2018
+++ xsrc/external/mit/libdrm/dist/xf86drm.c	Thu Jan 10 08:59:43 2019
@@ -31,9 +31,6 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>
@@ -128,7 +125,7 @@ struct drm_pciinfo {
 
 static drmServerInfoPtr drm_server_info;
 
-void drmSetServerInfo(drmServerInfoPtr info)
+drm_public void drmSetServerInfo(drmServerInfoPtr info)
 {
     drm_server_info = info;
 }
@@ -148,7 +145,7 @@ drmDebugPrint(const char *format, va_lis
     return vfprintf(stderr, format, ap);
 }
 
-void
+drm_public void
 drmMsg(const char *format, ...)
 {
     va_list ap;
@@ -168,17 +165,17 @@ drmMsg(const char *format, ...)
 
 static void *drmHashTable = NULL; /* Context switch callbacks */
 
-void *drmGetHashTable(void)
+drm_public void *drmGetHashTable(void)
 {
     return drmHashTable;
 }
 
-void *drmMalloc(int size)
+drm_public void *drmMalloc(int size)
 {
     return calloc(1, size);
 }
 
-void drmFree(void *pt)
+drm_public void drmFree(void *pt)
 {
     free(pt);
 }
@@ -186,7 +183,7 @@ void drmFree(void *pt)
 /**
  * Call ioctl, restarting if it is interupted
  */
-int
+drm_public int
 drmIoctl(int fd, unsigned long request, void *arg)
 {
     int ret;
@@ -206,7 +203,7 @@ static unsigned long drmGetKeyFromFd(int
     return st.st_rdev;
 }
 
-drmHashEntry *drmGetEntry(int fd)
+drm_public drmHashEntry *drmGetEntry(int fd)
 {
     unsigned long key = drmGetKeyFromFd(fd);
     void          *value;
@@ -297,7 +294,7 @@ static int drmMatchBusID(const char *id1
  * If any other failure happened then it will output error mesage using
  * drmMsg() call.
  */
-#if !defined(UDEV)
+#if !UDEV
 static int chown_check_return(const char *path, uid_t owner, gid_t group)
 {
         int rv;
@@ -336,7 +333,7 @@ static int drmOpenDevice(dev_t dev, int 
     int             fd;
     mode_t          devmode = DRM_DEV_MODE, serv_mode;
     gid_t           serv_group;
-#if !defined(UDEV)
+#if !UDEV
     int             isroot  = !geteuid();
     uid_t           user    = DRM_DEV_UID;
     gid_t           group   = DRM_DEV_GID;
@@ -365,7 +362,7 @@ static int drmOpenDevice(dev_t dev, int 
         devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
     }
 
-#if !defined(UDEV)
+#if !UDEV
     if (stat(DRM_DIR_NAME, &st)) {
         if (!isroot)
             return DRM_ERR_NOT_ROOT;
@@ -412,13 +409,13 @@ wait_for_udev:
     }
 #endif
 
-    fd = open(buf, O_RDWR, 0);
+    fd = open(buf, O_RDWR | O_CLOEXEC, 0);
     drmMsg("drmOpenDevice: open result is %d, (%s)\n",
            fd, fd < 0 ? strerror(errno) : "OK");
     if (fd >= 0)
         return fd;
 
-#if !defined(UDEV)
+#if !UDEV
     /* Check if the device node is not what we expect it to be, and recreate it
      * and try again if so.
      */
@@ -432,7 +429,7 @@ wait_for_udev:
             chmod(buf, devmode);
         }
     }
-    fd = open(buf, O_RDWR, 0);
+    fd = open(buf, O_RDWR | O_CLOEXEC, 0);
     drmMsg("drmOpenDevice: open result is %d, (%s)\n",
            fd, fd < 0 ? strerror(errno) : "OK");
     if (fd >= 0)
@@ -481,7 +478,7 @@ static int drmOpenMinor(int minor, int c
     };
 
     sprintf(buf, dev_name, DRM_DIR_NAME, minor);
-    if ((fd = open(buf, O_RDWR, 0)) >= 0)
+    if ((fd = open(buf, O_RDWR | O_CLOEXEC, 0)) >= 0)
         return fd;
     return -errno;
 }
@@ -497,7 +494,7 @@ static int drmOpenMinor(int minor, int c
  * minor and get version information.  For backward compatibility with older
  * Linux implementations, /proc/dri is also checked.
  */
-int drmAvailable(void)
+drm_public int drmAvailable(void)
 {
     drmVersionPtr version;
     int           retval = 0;
@@ -732,7 +729,7 @@ static int drmOpenByName(const char *nam
  * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
  * otherwise.
  */
-int drmOpen(const char *name, const char *busid)
+drm_public int drmOpen(const char *name, const char *busid)
 {
     return drmOpenWithType(name, busid, DRM_NODE_PRIMARY);
 }
@@ -753,7 +750,7 @@ int drmOpen(const char *name, const char
  * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
  * otherwise.
  */
-int drmOpenWithType(const char *name, const char *busid, int type)
+drm_public int drmOpenWithType(const char *name, const char *busid, int type)
 {
     if (!drmAvailable() && name != NULL && drm_server_info &&
         drm_server_info->load_module) {
@@ -776,12 +773,12 @@ int drmOpenWithType(const char *name, co
     return -1;
 }
 
-int drmOpenControl(int minor)
+drm_public int drmOpenControl(int minor)
 {
     return drmOpenMinor(minor, 0, DRM_NODE_CONTROL);
 }
 
-int drmOpenRender(int minor)
+drm_public int drmOpenRender(int minor)
 {
     return drmOpenMinor(minor, 0, DRM_NODE_RENDER);
 }
@@ -795,7 +792,7 @@ int drmOpenRender(int minor)
  * It frees the memory pointed by \p %v as well as all the non-null strings
  * pointers in it.
  */
-void drmFreeVersion(drmVersionPtr v)
+drm_public void drmFreeVersion(drmVersionPtr v)
 {
     if (!v)
         return;
@@ -865,7 +862,7 @@ static void drmCopyVersion(drmVersionPtr
  * first with zeros to get the string lengths, and then the actually strings.
  * It also null-terminates them since they might not be already.
  */
-drmVersionPtr drmGetVersion(int fd)
+drm_public drmVersionPtr drmGetVersion(int fd)
 {
     drmVersionPtr retval;
     drm_version_t *version = drmMalloc(sizeof(*version));
@@ -913,7 +910,7 @@ drmVersionPtr drmGetVersion(int fd)
  * This function allocates and fills a drm_version structure with a hard coded
  * version number.
  */
-drmVersionPtr drmGetLibVersion(int fd)
+drm_public drmVersionPtr drmGetLibVersion(int fd)
 {
     drm_version_t *version = drmMalloc(sizeof(*version));
 
@@ -934,7 +931,7 @@ drmVersionPtr drmGetLibVersion(int fd)
     return (drmVersionPtr)version;
 }
 
-int drmGetCap(int fd, uint64_t capability, uint64_t *value)
+drm_public int drmGetCap(int fd, uint64_t capability, uint64_t *value)
 {
     struct drm_get_cap cap;
     int ret;
@@ -950,7 +947,7 @@ int drmGetCap(int fd, uint64_t capabilit
     return 0;
 }
 
-int drmSetClientCap(int fd, uint64_t capability, uint64_t value)
+drm_public int drmSetClientCap(int fd, uint64_t capability, uint64_t value)
 {
     struct drm_set_client_cap cap;
 
@@ -969,7 +966,7 @@ int drmSetClientCap(int fd, uint64_t cap
  * \internal
  * This function is just frees the memory pointed by \p busid.
  */
-void drmFreeBusid(const char *busid)
+drm_public void drmFreeBusid(const char *busid)
 {
     drmFree((void *)busid);
 }
@@ -987,7 +984,7 @@ void drmFreeBusid(const char *busid)
  * get the string length and data, passing the arguments in a drm_unique
  * structure.
  */
-char *drmGetBusid(int fd)
+drm_public char *drmGetBusid(int fd)
 {
     drm_unique_t u;
 
@@ -1018,7 +1015,7 @@ char *drmGetBusid(int fd)
  * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing
  * the arguments in a drm_unique structure.
  */
-int drmSetBusid(int fd, const char *busid)
+drm_public int drmSetBusid(int fd, const char *busid)
 {
     drm_unique_t u;
 
@@ -1032,7 +1029,7 @@ int drmSetBusid(int fd, const char *busi
     return 0;
 }
 
-int drmGetMagic(int fd, drm_magic_t * magic)
+drm_public int drmGetMagic(int fd, drm_magic_t * magic)
 {
     drm_auth_t auth;
 
@@ -1045,7 +1042,7 @@ int drmGetMagic(int fd, drm_magic_t * ma
     return 0;
 }
 
-int drmAuthMagic(int fd, drm_magic_t magic)
+drm_public int drmAuthMagic(int fd, drm_magic_t magic)
 {
     drm_auth_t auth;
 
@@ -1106,8 +1103,8 @@ int drmAuthMagic(int fd, drm_magic_t mag
  * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
  * the arguments in a drm_map structure.
  */
-int drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type,
-              drmMapFlags flags, drm_handle_t *handle)
+drm_public int drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type,
+                         drmMapFlags flags, drm_handle_t *handle)
 {
     drm_map_t map;
 
@@ -1123,7 +1120,7 @@ int drmAddMap(int fd, drm_handle_t offse
     return 0;
 }
 
-int drmRmMap(int fd, drm_handle_t handle)
+drm_public int drmRmMap(int fd, drm_handle_t handle)
 {
     drm_map_t map;
 
@@ -1151,8 +1148,8 @@ int drmRmMap(int fd, drm_handle_t handle
  *
  * \sa drm_buf_desc.
  */
-int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
-               int agp_offset)
+drm_public int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
+                          int agp_offset)
 {
     drm_buf_desc_t request;
 
@@ -1167,7 +1164,7 @@ int drmAddBufs(int fd, int count, int si
     return request.count;
 }
 
-int drmMarkBufs(int fd, double low, double high)
+drm_public int drmMarkBufs(int fd, double low, double high)
 {
     drm_buf_info_t info;
     int            i;
@@ -1218,7 +1215,7 @@ int drmMarkBufs(int fd, double low, doub
  * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing
  * the arguments in a drm_buf_free structure.
  */
-int drmFreeBufs(int fd, int count, int *list)
+drm_public int drmFreeBufs(int fd, int count, int *list)
 {
     drm_buf_free_t request;
 
@@ -1239,7 +1236,7 @@ int drmFreeBufs(int fd, int count, int *
  * \internal
  * This function closes the file descriptor.
  */
-int drmClose(int fd)
+drm_public int drmClose(int fd)
 {
     unsigned long key    = drmGetKeyFromFd(fd);
     drmHashEntry  *entry = drmGetEntry(fd);
@@ -1270,7 +1267,8 @@ int drmClose(int fd)
  * \internal
  * This function is a wrapper for mmap().
  */
-int drmMap(int fd, drm_handle_t handle, drmSize size, drmAddressPtr address)
+drm_public int drmMap(int fd, drm_handle_t handle, drmSize size,
+                      drmAddressPtr address)
 {
     static unsigned long pagesize_mask = 0;
 
@@ -1300,12 +1298,12 @@ int drmMap(int fd, drm_handle_t handle, 
  * \internal
  * This function is a wrapper for munmap().
  */
-int drmUnmap(drmAddress address, drmSize size)
+drm_public int drmUnmap(drmAddress address, drmSize size)
 {
     return drm_munmap(address, size);
 }
 
-drmBufInfoPtr drmGetBufInfo(int fd)
+drm_public drmBufInfoPtr drmGetBufInfo(int fd)
 {
     drm_buf_info_t info;
     drmBufInfoPtr  retval;
@@ -1355,7 +1353,7 @@ drmBufInfoPtr drmGetBufInfo(int fd)
  * information about the buffers in a drm_buf_map structure into the
  * client-visible data structures.
  */
-drmBufMapPtr drmMapBufs(int fd)
+drm_public drmBufMapPtr drmMapBufs(int fd)
 {
     drm_buf_map_t bufs;
     drmBufMapPtr  retval;
@@ -1400,7 +1398,7 @@ drmBufMapPtr drmMapBufs(int fd)
  * Calls munmap() for every buffer stored in \p bufs and frees the
  * memory allocated by drmMapBufs().
  */
-int drmUnmapBufs(drmBufMapPtr bufs)
+drm_public int drmUnmapBufs(drmBufMapPtr bufs)
 {
     int i;
 
@@ -1428,7 +1426,7 @@ int drmUnmapBufs(drmBufMapPtr bufs)
  * Assemble the arguments into a drm_dma structure and keeps issuing the
  * DRM_IOCTL_DMA ioctl until success or until maximum number of retries.
  */
-int drmDMA(int fd, drmDMAReqPtr request)
+drm_public int drmDMA(int fd, drmDMAReqPtr request)
 {
     drm_dma_t dma;
     int ret, i = 0;
@@ -1471,7 +1469,7 @@ int drmDMA(int fd, drmDMAReqPtr request)
  * This function translates the arguments into a drm_lock structure and issue
  * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired.
  */
-int drmGetLock(int fd, drm_context_t context, drmLockFlags flags)
+drm_public int drmGetLock(int fd, drm_context_t context, drmLockFlags flags)
 {
     drm_lock_t lock;
 
@@ -1502,7 +1500,7 @@ int drmGetLock(int fd, drm_context_t con
  * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the
  * argument in a drm_lock structure.
  */
-int drmUnlock(int fd, drm_context_t context)
+drm_public int drmUnlock(int fd, drm_context_t context)
 {
     drm_lock_t lock;
 
@@ -1511,7 +1509,7 @@ int drmUnlock(int fd, drm_context_t cont
     return drmIoctl(fd, DRM_IOCTL_UNLOCK, &lock);
 }
 
-drm_context_t *drmGetReservedContextList(int fd, int *count)
+drm_public drm_context_t *drmGetReservedContextList(int fd, int *count)
 {
     drm_ctx_res_t res;
     drm_ctx_t     *list;
@@ -1548,7 +1546,7 @@ err_free_context:
     return NULL;
 }
 
-void drmFreeReservedContextList(drm_context_t *pt)
+drm_public void drmFreeReservedContextList(drm_context_t *pt)
 {
     drmFree(pt);
 }
@@ -1571,7 +1569,7 @@ void drmFreeReservedContextList(drm_cont
  * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the
  * argument in a drm_ctx structure.
  */
-int drmCreateContext(int fd, drm_context_t *handle)
+drm_public int drmCreateContext(int fd, drm_context_t *handle)
 {
     drm_ctx_t ctx;
 
@@ -1582,7 +1580,7 @@ int drmCreateContext(int fd, drm_context
     return 0;
 }
 
-int drmSwitchToContext(int fd, drm_context_t context)
+drm_public int drmSwitchToContext(int fd, drm_context_t context)
 {
     drm_ctx_t ctx;
 
@@ -1593,7 +1591,8 @@ int drmSwitchToContext(int fd, drm_conte
     return 0;
 }
 
-int drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags)
+drm_public int drmSetContextFlags(int fd, drm_context_t context,
+                                  drm_context_tFlags flags)
 {
     drm_ctx_t ctx;
 
@@ -1614,8 +1613,8 @@ int drmSetContextFlags(int fd, drm_conte
     return 0;
 }
 
-int drmGetContextFlags(int fd, drm_context_t context,
-                       drm_context_tFlagsPtr flags)
+drm_public int drmGetContextFlags(int fd, drm_context_t context,
+                                  drm_context_tFlagsPtr flags)
 {
     drm_ctx_t ctx;
 
@@ -1648,7 +1647,7 @@ int drmGetContextFlags(int fd, drm_conte
  * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the
  * argument in a drm_ctx structure.
  */
-int drmDestroyContext(int fd, drm_context_t handle)
+drm_public int drmDestroyContext(int fd, drm_context_t handle)
 {
     drm_ctx_t ctx;
 
@@ -1659,7 +1658,7 @@ int drmDestroyContext(int fd, drm_contex
     return 0;
 }
 
-int drmCreateDrawable(int fd, drm_drawable_t *handle)
+drm_public int drmCreateDrawable(int fd, drm_drawable_t *handle)
 {
     drm_draw_t draw;
 
@@ -1670,7 +1669,7 @@ int drmCreateDrawable(int fd, drm_drawab
     return 0;
 }
 
-int drmDestroyDrawable(int fd, drm_drawable_t handle)
+drm_public int drmDestroyDrawable(int fd, drm_drawable_t handle)
 {
     drm_draw_t draw;
 
@@ -1681,9 +1680,9 @@ int drmDestroyDrawable(int fd, drm_drawa
     return 0;
 }
 
-int drmUpdateDrawableInfo(int fd, drm_drawable_t handle,
-                          drm_drawable_info_type_t type, unsigned int num,
-                          void *data)
+drm_public int drmUpdateDrawableInfo(int fd, drm_drawable_t handle,
+                                     drm_drawable_info_type_t type,
+                                     unsigned int num, void *data)
 {
     drm_update_draw_t update;
 
@@ -1699,7 +1698,8 @@ int drmUpdateDrawableInfo(int fd, drm_dr
     return 0;
 }
 
-int drmCrtcGetSequence(int fd, uint32_t crtcId, uint64_t *sequence, uint64_t *ns)
+drm_public int drmCrtcGetSequence(int fd, uint32_t crtcId, uint64_t *sequence,
+                                  uint64_t *ns)
 {
     struct drm_crtc_get_sequence get_seq;
     int ret;
@@ -1717,8 +1717,10 @@ int drmCrtcGetSequence(int fd, uint32_t 
     return 0;
 }
 
-int drmCrtcQueueSequence(int fd, uint32_t crtcId, uint32_t flags, uint64_t sequence,
-                         uint64_t *sequence_queued, uint64_t user_data)
+drm_public int drmCrtcQueueSequence(int fd, uint32_t crtcId, uint32_t flags,
+                                    uint64_t sequence,
+                                    uint64_t *sequence_queued,
+                                    uint64_t user_data)
 {
     struct drm_crtc_queue_sequence queue_seq;
     int ret;
@@ -1748,7 +1750,7 @@ int drmCrtcQueueSequence(int fd, uint32_
  * \internal
  * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl.
  */
-int drmAgpAcquire(int fd)
+drm_public int drmAgpAcquire(int fd)
 {
     if (drmIoctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL))
         return -errno;
@@ -1766,7 +1768,7 @@ int drmAgpAcquire(int fd)
  * \internal
  * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl.
  */
-int drmAgpRelease(int fd)
+drm_public int drmAgpRelease(int fd)
 {
     if (drmIoctl(fd, DRM_IOCTL_AGP_RELEASE, NULL))
         return -errno;
@@ -1786,7 +1788,7 @@ int drmAgpRelease(int fd)
  * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the
  * argument in a drm_agp_mode structure.
  */
-int drmAgpEnable(int fd, unsigned long mode)
+drm_public int drmAgpEnable(int fd, unsigned long mode)
 {
     drm_agp_mode_t m;
 
@@ -1814,8 +1816,8 @@ int drmAgpEnable(int fd, unsigned long m
  * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the
  * arguments in a drm_agp_buffer structure.
  */
-int drmAgpAlloc(int fd, unsigned long size, unsigned long type,
-                unsigned long *address, drm_handle_t *handle)
+drm_public int drmAgpAlloc(int fd, unsigned long size, unsigned long type,
+                           unsigned long *address, drm_handle_t *handle)
 {
     drm_agp_buffer_t b;
 
@@ -1844,7 +1846,7 @@ int drmAgpAlloc(int fd, unsigned long si
  * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the
  * argument in a drm_agp_buffer structure.
  */
-int drmAgpFree(int fd, drm_handle_t handle)
+drm_public int drmAgpFree(int fd, drm_handle_t handle)
 {
     drm_agp_buffer_t b;
 
@@ -1869,7 +1871,7 @@ int drmAgpFree(int fd, drm_handle_t hand
  * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the
  * argument in a drm_agp_binding structure.
  */
-int drmAgpBind(int fd, drm_handle_t handle, unsigned long offset)
+drm_public int drmAgpBind(int fd, drm_handle_t handle, unsigned long offset)
 {
     drm_agp_binding_t b;
 
@@ -1894,7 +1896,7 @@ int drmAgpBind(int fd, drm_handle_t hand
  * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing
  * the argument in a drm_agp_binding structure.
  */
-int drmAgpUnbind(int fd, drm_handle_t handle)
+drm_public int drmAgpUnbind(int fd, drm_handle_t handle)
 {
     drm_agp_binding_t b;
 
@@ -1917,7 +1919,7 @@ int drmAgpUnbind(int fd, drm_handle_t ha
  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
  * necessary information in a drm_agp_info structure.
  */
-int drmAgpVersionMajor(int fd)
+drm_public int drmAgpVersionMajor(int fd)
 {
     drm_agp_info_t i;
 
@@ -1940,7 +1942,7 @@ int drmAgpVersionMajor(int fd)
  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
  * necessary information in a drm_agp_info structure.
  */
-int drmAgpVersionMinor(int fd)
+drm_public int drmAgpVersionMinor(int fd)
 {
     drm_agp_info_t i;
 
@@ -1963,7 +1965,7 @@ int drmAgpVersionMinor(int fd)
  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
  * necessary information in a drm_agp_info structure.
  */
-unsigned long drmAgpGetMode(int fd)
+drm_public unsigned long drmAgpGetMode(int fd)
 {
     drm_agp_info_t i;
 
@@ -1986,7 +1988,7 @@ unsigned long drmAgpGetMode(int fd)
  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
  * necessary information in a drm_agp_info structure.
  */
-unsigned long drmAgpBase(int fd)
+drm_public unsigned long drmAgpBase(int fd)
 {
     drm_agp_info_t i;
 
@@ -2009,7 +2011,7 @@ unsigned long drmAgpBase(int fd)
  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
  * necessary information in a drm_agp_info structure.
  */
-unsigned long drmAgpSize(int fd)
+drm_public unsigned long drmAgpSize(int fd)
 {
     drm_agp_info_t i;
 
@@ -2032,7 +2034,7 @@ unsigned long drmAgpSize(int fd)
  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
  * necessary information in a drm_agp_info structure.
  */
-unsigned long drmAgpMemoryUsed(int fd)
+drm_public unsigned long drmAgpMemoryUsed(int fd)
 {
     drm_agp_info_t i;
 
@@ -2055,7 +2057,7 @@ unsigned long drmAgpMemoryUsed(int fd)
  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
  * necessary information in a drm_agp_info structure.
  */
-unsigned long drmAgpMemoryAvail(int fd)
+drm_public unsigned long drmAgpMemoryAvail(int fd)
 {
     drm_agp_info_t i;
 
@@ -2078,7 +2080,7 @@ unsigned long drmAgpMemoryAvail(int fd)
  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
  * necessary information in a drm_agp_info structure.
  */
-unsigned int drmAgpVendorId(int fd)
+drm_public unsigned int drmAgpVendorId(int fd)
 {
     drm_agp_info_t i;
 
@@ -2101,7 +2103,7 @@ unsigned int drmAgpVendorId(int fd)
  * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
  * necessary information in a drm_agp_info structure.
  */
-unsigned int drmAgpDeviceId(int fd)
+drm_public unsigned int drmAgpDeviceId(int fd)
 {
     drm_agp_info_t i;
 
@@ -2112,7 +2114,8 @@ unsigned int drmAgpDeviceId(int fd)
     return i.id_device;
 }
 
-int drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle)
+drm_public int drmScatterGatherAlloc(int fd, unsigned long size,
+                                     drm_handle_t *handle)
 {
     drm_scatter_gather_t sg;
 
@@ -2126,7 +2129,7 @@ int drmScatterGatherAlloc(int fd, unsign
     return 0;
 }
 
-int drmScatterGatherFree(int fd, drm_handle_t handle)
+drm_public int drmScatterGatherFree(int fd, drm_handle_t handle)
 {
     drm_scatter_gather_t sg;
 
@@ -2148,7 +2151,7 @@ int drmScatterGatherFree(int fd, drm_han
  * \internal
  * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl.
  */
-int drmWaitVBlank(int fd, drmVBlankPtr vbl)
+drm_public int drmWaitVBlank(int fd, drmVBlankPtr vbl)
 {
     struct timespec timeout, cur;
     int ret;
@@ -2180,7 +2183,7 @@ out:
     return ret;
 }
 
-int drmError(int err, const char *label)
+drm_public int drmError(int err, const char *label)
 {
     switch (err) {
     case DRM_ERR_NO_DEVICE:
@@ -2217,7 +2220,7 @@ int drmError(int err, const char *label)
  * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
  * argument in a drm_control structure.
  */
-int drmCtlInstHandler(int fd, int irq)
+drm_public int drmCtlInstHandler(int fd, int irq)
 {
     drm_control_t ctl;
 
@@ -2241,7 +2244,7 @@ int drmCtlInstHandler(int fd, int irq)
  * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
  * argument in a drm_control structure.
  */
-int drmCtlUninstHandler(int fd)
+drm_public int drmCtlUninstHandler(int fd)
 {
     drm_control_t ctl;
 
@@ -2253,7 +2256,7 @@ int drmCtlUninstHandler(int fd)
     return 0;
 }
 
-int drmFinish(int fd, int context, drmLockFlags flags)
+drm_public int drmFinish(int fd, int context, drmLockFlags flags)
 {
     drm_lock_t lock;
 
@@ -2284,7 +2287,8 @@ int drmFinish(int fd, int context, drmLo
  * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the
  * arguments in a drm_irq_busid structure.
  */
-int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum)
+drm_public int drmGetInterruptFromBusID(int fd, int busnum, int devnum,
+                                        int funcnum)
 {
     drm_irq_busid_t p;
 
@@ -2297,7 +2301,7 @@ int drmGetInterruptFromBusID(int fd, int
     return p.irq;
 }
 
-int drmAddContextTag(int fd, drm_context_t context, void *tag)
+drm_public int drmAddContextTag(int fd, drm_context_t context, void *tag)
 {
     drmHashEntry  *entry = drmGetEntry(fd);
 
@@ -2308,14 +2312,14 @@ int drmAddContextTag(int fd, drm_context
     return 0;
 }
 
-int drmDelContextTag(int fd, drm_context_t context)
+drm_public int drmDelContextTag(int fd, drm_context_t context)
 {
     drmHashEntry  *entry = drmGetEntry(fd);
 
     return drmHashDelete(entry->tagTable, context);
 }
 
-void *drmGetContextTag(int fd, drm_context_t context)
+drm_public void *drmGetContextTag(int fd, drm_context_t context)
 {
     drmHashEntry  *entry = drmGetEntry(fd);
     void          *value;
@@ -2326,8 +2330,8 @@ void *drmGetContextTag(int fd, drm_conte
     return value;
 }
 
-int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
-                                drm_handle_t handle)
+drm_public int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
+                                           drm_handle_t handle)
 {
     drm_ctx_priv_map_t map;
 
@@ -2340,8 +2344,8 @@ int drmAddContextPrivateMapping(int fd, 
     return 0;
 }
 
-int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
-                                drm_handle_t *handle)
+drm_public int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
+                                           drm_handle_t *handle)
 {
     drm_ctx_priv_map_t map;
 
@@ -2356,9 +2360,9 @@ int drmGetContextPrivateMapping(int fd, 
     return 0;
 }
 
-int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size,
-              drmMapType *type, drmMapFlags *flags, drm_handle_t *handle,
-              int *mtrr)
+drm_public int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size,
+                         drmMapType *type, drmMapFlags *flags,
+                         drm_handle_t *handle, int *mtrr)
 {
     drm_map_t map;
 
@@ -2375,8 +2379,8 @@ int drmGetMap(int fd, int idx, drm_handl
     return 0;
 }
 
-int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
-                 unsigned long *magic, unsigned long *iocs)
+drm_public int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
+                            unsigned long *magic, unsigned long *iocs)
 {
     drm_client_t client;
 
@@ -2392,7 +2396,7 @@ int drmGetClient(int fd, int idx, int *a
     return 0;
 }
 
-int drmGetStats(int fd, drmStatsT *stats)
+drm_public int drmGetStats(int fd, drmStatsT *stats)
 {
     drm_stats_t s;
     unsigned    i;
@@ -2530,7 +2534,7 @@ int drmGetStats(int fd, drmStatsT *stats
  * It issues a read-write ioctl given by
  * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
  */
-int drmSetInterfaceVersion(int fd, drmSetVersion *version)
+drm_public int drmSetInterfaceVersion(int fd, drmSetVersion *version)
 {
     int retcode = 0;
     drm_set_version_t sv;
@@ -2565,7 +2569,7 @@ int drmSetInterfaceVersion(int fd, drmSe
  * It issues a ioctl given by
  * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
  */
-int drmCommandNone(int fd, unsigned long drmCommandIndex)
+drm_public int drmCommandNone(int fd, unsigned long drmCommandIndex)
 {
     unsigned long request;
 
@@ -2592,8 +2596,8 @@ int drmCommandNone(int fd, unsigned long
  * It issues a read ioctl given by
  * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
  */
-int drmCommandRead(int fd, unsigned long drmCommandIndex, void *data,
-                   unsigned long size)
+drm_public int drmCommandRead(int fd, unsigned long drmCommandIndex,
+                              void *data, unsigned long size)
 {
     unsigned long request;
 
@@ -2621,8 +2625,8 @@ int drmCommandRead(int fd, unsigned long
  * It issues a write ioctl given by
  * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
  */
-int drmCommandWrite(int fd, unsigned long drmCommandIndex, void *data,
-                    unsigned long size)
+drm_public int drmCommandWrite(int fd, unsigned long drmCommandIndex,
+                               void *data, unsigned long size)
 {
     unsigned long request;
 
@@ -2650,8 +2654,8 @@ int drmCommandWrite(int fd, unsigned lon
  * It issues a read-write ioctl given by
  * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
  */
-int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data,
-                        unsigned long size)
+drm_public int drmCommandWriteRead(int fd, unsigned long drmCommandIndex,
+                                   void *data, unsigned long size)
 {
     unsigned long request;
 
@@ -2673,14 +2677,13 @@ static struct {
 
 static int nr_fds = 0;
 
-int drmOpenOnce(void *unused,
-                const char *BusID,
-                int *newlyopened)
+drm_public int drmOpenOnce(void *unused, const char *BusID, int *newlyopened)
 {
     return drmOpenOnceWithType(BusID, newlyopened, DRM_NODE_PRIMARY);
 }
 
-int drmOpenOnceWithType(const char *BusID, int *newlyopened, int type)
+drm_public int drmOpenOnceWithType(const char *BusID, int *newlyopened,
+                                   int type)
 {
     int i;
     int fd;
@@ -2713,7 +2716,7 @@ int drmOpenOnceWithType(const char *BusI
     return fd;
 }
 
-void drmCloseOnce(int fd)
+drm_public void drmCloseOnce(int fd)
 {
     int i;
 
@@ -2732,17 +2735,17 @@ void drmCloseOnce(int fd)
     }
 }
 
-int drmSetMaster(int fd)
+drm_public int drmSetMaster(int fd)
 {
         return drmIoctl(fd, DRM_IOCTL_SET_MASTER, NULL);
 }
 
-int drmDropMaster(int fd)
+drm_public int drmDropMaster(int fd)
 {
         return drmIoctl(fd, DRM_IOCTL_DROP_MASTER, NULL);
 }
 
-char *drmGetDeviceNameFromFd(int fd)
+drm_public char *drmGetDeviceNameFromFd(int fd)
 {
     char name[128];
     struct stat sbuf;
@@ -2768,7 +2771,21 @@ char *drmGetDeviceNameFromFd(int fd)
     return strdup(name);
 }
 
-int drmGetNodeTypeFromFd(int fd)
+static bool drmNodeIsDRM(int maj, int min)
+{
+#ifdef __linux__
+    char path[64];
+    struct stat sbuf;
+
+    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device/drm",
+             maj, min);
+    return stat(path, &sbuf) == 0;
+#else
+    return maj == DRM_MAJOR;
+#endif
+}
+
+drm_public int drmGetNodeTypeFromFd(int fd)
 {
     struct stat sbuf;
     int maj, min, type;
@@ -2779,7 +2796,7 @@ int drmGetNodeTypeFromFd(int fd)
     maj = major(sbuf.st_rdev);
     min = minor(sbuf.st_rdev);
 
-    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) {
+    if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) {
         errno = EINVAL;
         return -1;
     }
@@ -2790,7 +2807,8 @@ int drmGetNodeTypeFromFd(int fd)
     return type;
 }
 
-int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd)
+drm_public int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags,
+                                  int *prime_fd)
 {
     struct drm_prime_handle args;
     int ret;
@@ -2807,7 +2825,7 @@ int drmPrimeHandleToFD(int fd, uint32_t 
     return 0;
 }
 
-int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
+drm_public int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
 {
     struct drm_prime_handle args;
     int ret;
@@ -2826,12 +2844,11 @@ static char *drmGetMinorNameForFD(int fd
 {
 #ifdef __linux__
     DIR *sysdir;
-    struct dirent *pent, *ent;
+    struct dirent *ent;
     struct stat sbuf;
     const char *name = drmGetMinorName(type);
     int len;
     char dev_name[64], buf[64];
-    long name_max;
     int maj, min;
 
     if (!name)
@@ -2845,7 +2862,7 @@ static char *drmGetMinorNameForFD(int fd
     maj = major(sbuf.st_rdev);
     min = minor(sbuf.st_rdev);
 
-    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+    if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
         return NULL;
 
     snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/device/drm", maj, min);
@@ -2854,30 +2871,18 @@ static char *drmGetMinorNameForFD(int fd
     if (!sysdir)
         return NULL;
 
-    name_max = fpathconf(dirfd(sysdir), _PC_NAME_MAX);
-    if (name_max == -1)
-        goto out_close_dir;
-
-    pent = malloc(offsetof(struct dirent, d_name) + name_max + 1);
-    if (pent == NULL)
-         goto out_close_dir;
-
-    while (readdir_r(sysdir, pent, &ent) == 0 && ent != NULL) {
+    while ((ent = readdir(sysdir))) {
         if (strncmp(ent->d_name, name, len) == 0) {
             snprintf(dev_name, sizeof(dev_name), DRM_DIR_NAME "/%s",
                  ent->d_name);
 
-            free(pent);
             closedir(sysdir);
-
             return strdup(dev_name);
         }
     }
 
-    free(pent);
-
-out_close_dir:
     closedir(sysdir);
+    return NULL;
 #else
     struct stat sbuf;
     char buf[PATH_MAX + 1];
@@ -2891,7 +2896,7 @@ out_close_dir:
     maj = major(sbuf.st_rdev);
     min = minor(sbuf.st_rdev);
 
-    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+    if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
         return NULL;
 
     switch (type) {
@@ -2918,15 +2923,14 @@ out_close_dir:
 
     return strdup(buf);
 #endif
-    return NULL;
 }
 
-char *drmGetPrimaryDeviceNameFromFd(int fd)
+drm_public char *drmGetPrimaryDeviceNameFromFd(int fd)
 {
     return drmGetMinorNameForFD(fd, DRM_NODE_PRIMARY);
 }
 
-char *drmGetRenderDeviceNameFromFd(int fd)
+drm_public char *drmGetRenderDeviceNameFromFd(int fd)
 {
     return drmGetMinorNameForFD(fd, DRM_NODE_RENDER);
 }
@@ -2975,6 +2979,9 @@ sysfs_uevent_get(const char *path, const
 }
 #endif
 
+/* Little white lie to avoid major rework of the existing code */
+#define DRM_BUS_VIRTIO 0x10
+
 static int drmParseSubsystemType(int maj, int min)
 {
 #ifdef __linux__
@@ -3004,6 +3011,9 @@ static int drmParseSubsystemType(int maj
     if (strncmp(name, "/host1x", 7) == 0)
         return DRM_BUS_HOST1X;
 
+    if (strncmp(name, "/virtio", 7) == 0)
+        return DRM_BUS_VIRTIO;
+
     return -EINVAL;
 #elif defined(__NetBSD__)
     int type, fd;
@@ -3072,16 +3082,32 @@ static int drmParseSubsystemType(int maj
 #endif
 }
 
+static void
+get_pci_path(int maj, int min, char *pci_path)
+{
+    char path[PATH_MAX + 1], *term;
+
+    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+    if (!realpath(path, pci_path)) {
+        strcpy(pci_path, path);
+        return;
+    }
+
+    term = strrchr(pci_path, '/');
+    if (term && strncmp(term, "/virtio", 7) == 0)
+        *term = 0;
+}
+
 static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info)
 {
 #ifdef __linux__
     unsigned int domain, bus, dev, func;
-    char path[PATH_MAX + 1], *value;
+    char pci_path[PATH_MAX + 1], *value;
     int num;
 
-    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+    get_pci_path(maj, min, pci_path);
 
-    value = sysfs_uevent_get(path, "PCI_SLOT_NAME");
+    value = sysfs_uevent_get(pci_path, "PCI_SLOT_NAME");
     if (!value)
         return -ENOENT;
 
@@ -3194,7 +3220,7 @@ static int drmParsePciBusInfo(int maj, i
 #endif
 }
 
-int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b)
+drm_public int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b)
 {
     if (a == NULL || b == NULL)
         return 0;
@@ -3261,14 +3287,15 @@ static int parse_separate_sysfs_files(in
       "subsystem_vendor",
       "subsystem_device",
     };
-    char path[PATH_MAX + 1];
+    char path[PATH_MAX + 1], pci_path[PATH_MAX + 1];
     unsigned int data[ARRAY_SIZE(attrs)];
     FILE *fp;
     int ret;
 
+    get_pci_path(maj, min, pci_path);
+
     for (unsigned i = ignore_revision ? 1 : 0; i < ARRAY_SIZE(attrs); i++) {
-        snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/%s", maj, min,
-                 attrs[i]);
+        snprintf(path, PATH_MAX, "%s/%s", pci_path, attrs[i]);
         fp = fopen(path, "r");
         if (!fp)
             return -errno;
@@ -3292,11 +3319,13 @@ static int parse_separate_sysfs_files(in
 static int parse_config_sysfs_file(int maj, int min,
                                    drmPciDeviceInfoPtr device)
 {
-    char path[PATH_MAX + 1];
+    char path[PATH_MAX + 1], pci_path[PATH_MAX + 1];
     unsigned char config[64];
     int fd, ret;
 
-    snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/config", maj, min);
+    get_pci_path(maj, min, pci_path);
+
+    snprintf(path, PATH_MAX, "%s/config", pci_path);
     fd = open(path, O_RDONLY);
     if (fd < 0)
         return -errno;
@@ -3433,7 +3462,7 @@ static void drmFreeHost1xDevice(drmDevic
     }
 }
 
-void drmFreeDevice(drmDevicePtr *device)
+drm_public void drmFreeDevice(drmDevicePtr *device)
 {
     if (device == NULL)
         return;
@@ -3454,7 +3483,7 @@ void drmFreeDevice(drmDevicePtr *device)
     *device = NULL;
 }
 
-void drmFreeDevices(drmDevicePtr devices[], int count)
+drm_public void drmFreeDevices(drmDevicePtr devices[], int count)
 {
     int i;
 
@@ -3865,6 +3894,53 @@ free_device:
     return ret;
 }
 
+static int
+process_device(drmDevicePtr *device, const char *d_name,
+               int req_subsystem_type,
+               bool fetch_deviceinfo, uint32_t flags)
+{
+    struct stat sbuf;
+    char node[PATH_MAX + 1];
+    int node_type, subsystem_type;
+    unsigned int maj, min;
+
+    node_type = drmGetNodeType(d_name);
+    if (node_type < 0)
+        return -1;
+
+    snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, d_name);
+    if (stat(node, &sbuf))
+        return -1;
+
+    maj = major(sbuf.st_rdev);
+    min = minor(sbuf.st_rdev);
+
+    if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
+        return -1;
+
+    subsystem_type = drmParseSubsystemType(maj, min);
+    if (req_subsystem_type != -1 && req_subsystem_type != subsystem_type)
+        return -1;
+
+    switch (subsystem_type) {
+    case DRM_BUS_PCI:
+    case DRM_BUS_VIRTIO:
+        return drmProcessPciDevice(device, node, node_type, maj, min,
+                                   fetch_deviceinfo, flags);
+    case DRM_BUS_USB:
+        return drmProcessUsbDevice(device, node, node_type, maj, min,
+                                   fetch_deviceinfo, flags);
+    case DRM_BUS_PLATFORM:
+        return drmProcessPlatformDevice(device, node, node_type, maj, min,
+                                        fetch_deviceinfo, flags);
+    case DRM_BUS_HOST1X:
+        return drmProcessHost1xDevice(device, node, node_type, maj, min,
+                                      fetch_deviceinfo, flags);
+    default:
+        return -1;
+   }
+}
+
 /* Consider devices located on the same bus as duplicate and fold the respective
  * entries into a single one.
  *
@@ -3894,6 +3970,28 @@ drm_device_validate_flags(uint32_t flags
         return (flags & ~DRM_DEVICE_GET_PCI_REVISION);
 }
 
+static bool
+drm_device_has_rdev(drmDevicePtr device, dev_t find_rdev)
+{
+    struct stat sbuf;
+
+    for (int i = 0; i < DRM_NODE_MAX; i++) {
+        if (device->available_nodes & 1 << i) {
+            if (stat(device->nodes[i], &sbuf) == 0 &&
+                sbuf.st_rdev == find_rdev)
+                return true;
+        }
+    }
+    return false;
+}
+
+/*
+ * The kernel drm core has a number of places that assume maximum of
+ * 3x64 devices nodes. That's 64 for each of primary, control and
+ * render nodes. Rounded it up to 256 for simplicity.
+ */
+#define MAX_DRM_NODES 256
+
 /**
  * Get information about the opened drm device
  *
@@ -3907,7 +4005,7 @@ drm_device_validate_flags(uint32_t flags
  * \note Unlike drmGetDevice it does not retrieve the pci device revision field
  * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set.
  */
-int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device)
+drm_public int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device)
 {
 #ifdef __OpenBSD__
     /*
@@ -3931,7 +4029,7 @@ int drmGetDevice2(int fd, uint32_t flags
     maj = major(sbuf.st_rdev);
     min = minor(sbuf.st_rdev);
 
-    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+    if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
         return -EINVAL;
 
     node_type = drmGetMinorType(min);
@@ -3974,16 +4072,14 @@ int drmGetDevice2(int fd, uint32_t flags
 
     return 0;
 #else
-    drmDevicePtr *local_devices;
+    drmDevicePtr local_devices[MAX_DRM_NODES];
     drmDevicePtr d;
     DIR *sysdir;
     struct dirent *dent;
     struct stat sbuf;
-    char node[PATH_MAX + 1];
-    int node_type, subsystem_type;
+    int subsystem_type;
     int maj, min;
     int ret, i, node_count;
-    int max_count = 16;
     dev_t find_rdev;
 
     if (drm_device_validate_flags(flags))
@@ -3999,112 +4095,52 @@ int drmGetDevice2(int fd, uint32_t flags
     maj = major(sbuf.st_rdev);
     min = minor(sbuf.st_rdev);
 
-    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+    if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
         return -EINVAL;
 
     subsystem_type = drmParseSubsystemType(maj, min);
-
-    local_devices = calloc(max_count, sizeof(drmDevicePtr));
-    if (local_devices == NULL)
-        return -ENOMEM;
+    if (subsystem_type < 0)
+        return subsystem_type;
 
     sysdir = opendir(DRM_DIR_NAME);
-    if (!sysdir) {
-        ret = -errno;
-        goto free_locals;
-    }
+    if (!sysdir)
+        return -errno;
 
     i = 0;
     while ((dent = readdir(sysdir))) {
-        node_type = drmGetNodeType(dent->d_name);
-        if (node_type < 0)
-            continue;
-
-        snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name);
-        if (stat(node, &sbuf))
-            continue;
-
-        maj = major(sbuf.st_rdev);
-        min = minor(sbuf.st_rdev);
-
-        if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
-            continue;
-
-        if (drmParseSubsystemType(maj, min) != subsystem_type)
+        ret = process_device(&d, dent->d_name, subsystem_type, true, flags);
+        if (ret)
             continue;
 
-        switch (subsystem_type) {
-        case DRM_BUS_PCI:
-            ret = drmProcessPciDevice(&d, node, node_type, maj, min, true, flags);
-            if (ret)
-                continue;
-
-            break;
-
-        case DRM_BUS_USB:
-            ret = drmProcessUsbDevice(&d, node, node_type, maj, min, true, flags);
-            if (ret)
-                continue;
-
-            break;
-
-        case DRM_BUS_PLATFORM:
-            ret = drmProcessPlatformDevice(&d, node, node_type, maj, min, true, flags);
-            if (ret)
-                continue;
-
-            break;
-
-        case DRM_BUS_HOST1X:
-            ret = drmProcessHost1xDevice(&d, node, node_type, maj, min, true, flags);
-            if (ret)
-                continue;
-
+        if (i >= MAX_DRM_NODES) {
+            fprintf(stderr, "More than %d drm nodes detected. "
+                    "Please report a bug - that should not happen.\n"
+                    "Skipping extra nodes\n", MAX_DRM_NODES);
             break;
-
-        default:
-            continue;
-        }
-
-        if (i >= max_count) {
-            drmDevicePtr *temp;
-
-            max_count += 16;
-            temp = realloc(local_devices, max_count * sizeof(drmDevicePtr));
-            if (!temp)
-                goto free_devices;
-            local_devices = temp;
         }
-
-        /* store target at local_devices[0] for ease to use below */
-        if (find_rdev == sbuf.st_rdev && i) {
-            local_devices[i] = local_devices[0];
-            local_devices[0] = d;
-        }
-        else
-            local_devices[i] = d;
+        local_devices[i] = d;
         i++;
     }
     node_count = i;
 
     drmFoldDuplicatedDevices(local_devices, node_count);
 
-    *device = local_devices[0];
-    drmFreeDevices(&local_devices[1], node_count - 1);
+    *device = NULL;
+
+    for (i = 0; i < node_count; i++) {
+        if (!local_devices[i])
+            continue;
+
+        if (drm_device_has_rdev(local_devices[i], find_rdev))
+            *device = local_devices[i];
+        else
+            drmFreeDevice(&local_devices[i]);
+    }
 
     closedir(sysdir);
-    free(local_devices);
     if (*device == NULL)
         return -ENODEV;
     return 0;
-
-free_devices:
-    drmFreeDevices(local_devices, i);
-    closedir(sysdir);
-
-free_locals:
-    free(local_devices);
-    return ret;
 #endif
 }
 
@@ -4117,7 +4153,7 @@ free_locals:
  *
  * \return zero on success, negative error code otherwise.
  */
-int drmGetDevice(int fd, drmDevicePtr *device)
+drm_public int drmGetDevice(int fd, drmDevicePtr *device)
 {
     return drmGetDevice2(fd, DRM_DEVICE_GET_PCI_REVISION, device);
 }
@@ -4138,100 +4174,34 @@ int drmGetDevice(int fd, drmDevicePtr *d
  * \note Unlike drmGetDevices it does not retrieve the pci device revision field
  * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set.
  */
-int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices)
+drm_public int drmGetDevices2(uint32_t flags, drmDevicePtr devices[],
+                              int max_devices)
 {
-    drmDevicePtr *local_devices;
+    drmDevicePtr local_devices[MAX_DRM_NODES];
     drmDevicePtr device;
     DIR *sysdir;
     struct dirent *dent;
-    struct stat sbuf;
-    char node[PATH_MAX + 1];
-    int node_type, subsystem_type;
-    int maj, min;
     int ret, i, node_count, device_count;
-    int max_count = 16;
 
     if (drm_device_validate_flags(flags))
         return -EINVAL;
 
-    local_devices = calloc(max_count, sizeof(drmDevicePtr));
-    if (local_devices == NULL)
-        return -ENOMEM;
-
     sysdir = opendir(DRM_DIR_NAME);
-    if (!sysdir) {
-        ret = -errno;
-        goto free_locals;
-    }
+    if (!sysdir)
+        return -errno;
 
     i = 0;
     while ((dent = readdir(sysdir))) {
-        node_type = drmGetNodeType(dent->d_name);
-        if (node_type < 0)
-            continue;
-
-        snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name);
-        if (stat(node, &sbuf))
-            continue;
-
-        maj = major(sbuf.st_rdev);
-        min = minor(sbuf.st_rdev);
-
-        if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
-            continue;
-
-        subsystem_type = drmParseSubsystemType(maj, min);
-
-        if (subsystem_type < 0)
+        ret = process_device(&device, dent->d_name, -1, devices != NULL, flags);
+        if (ret)
             continue;
 
-        switch (subsystem_type) {
-        case DRM_BUS_PCI:
-            ret = drmProcessPciDevice(&device, node, node_type,
-                                      maj, min, devices != NULL, flags);
-            if (ret)
-                continue;
-
-            break;
-
-        case DRM_BUS_USB:
-            ret = drmProcessUsbDevice(&device, node, node_type, maj, min,
-                                      devices != NULL, flags);
-            if (ret)
-                continue;
-
+        if (i >= MAX_DRM_NODES) {
+            fprintf(stderr, "More than %d drm nodes detected. "
+                    "Please report a bug - that should not happen.\n"
+                    "Skipping extra nodes\n", MAX_DRM_NODES);
             break;
-
-        case DRM_BUS_PLATFORM:
-            ret = drmProcessPlatformDevice(&device, node, node_type, maj, min,
-                                           devices != NULL, flags);
-            if (ret)
-                continue;
-
-            break;
-
-        case DRM_BUS_HOST1X:
-            ret = drmProcessHost1xDevice(&device, node, node_type, maj, min,
-                                         devices != NULL, flags);
-            if (ret)
-                continue;
-
-            break;
-
-        default:
-            continue;
         }
-
-        if (i >= max_count) {
-            drmDevicePtr *temp;
-
-            max_count += 16;
-            temp = realloc(local_devices, max_count * sizeof(drmDevicePtr));
-            if (!temp)
-                goto free_devices;
-            local_devices = temp;
-        }
-
         local_devices[i] = device;
         i++;
     }
@@ -4253,16 +4223,7 @@ int drmGetDevices2(uint32_t flags, drmDe
     }
 
     closedir(sysdir);
-    free(local_devices);
     return device_count;
-
-free_devices:
-    drmFreeDevices(local_devices, i);
-    closedir(sysdir);
-
-free_locals:
-    free(local_devices);
-    return ret;
 }
 
 /**
@@ -4277,12 +4238,12 @@ free_locals:
  *         alternatively the number of devices stored in devices[], which is
  *         capped by the max_devices.
  */
-int drmGetDevices(drmDevicePtr devices[], int max_devices)
+drm_public int drmGetDevices(drmDevicePtr devices[], int max_devices)
 {
     return drmGetDevices2(DRM_DEVICE_GET_PCI_REVISION, devices, max_devices);
 }
 
-char *drmGetDeviceNameFromFd2(int fd)
+drm_public char *drmGetDeviceNameFromFd2(int fd)
 {
 #ifdef __linux__
     struct stat sbuf;
@@ -4295,7 +4256,7 @@ char *drmGetDeviceNameFromFd2(int fd)
     maj = major(sbuf.st_rdev);
     min = minor(sbuf.st_rdev);
 
-    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+    if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
         return NULL;
 
     snprintf(path, sizeof(path), "/sys/dev/char/%d:%d", maj, min);
@@ -4321,7 +4282,7 @@ char *drmGetDeviceNameFromFd2(int fd)
     maj = major(sbuf.st_rdev);
     min = minor(sbuf.st_rdev);
 
-    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+    if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
         return NULL;
 
     node_type = drmGetMinorType(min);
@@ -4354,7 +4315,7 @@ char *drmGetDeviceNameFromFd2(int fd)
 #endif
 }
 
-int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle)
+drm_public int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle)
 {
     struct drm_syncobj_create args;
     int ret;
@@ -4369,7 +4330,7 @@ int drmSyncobjCreate(int fd, uint32_t fl
     return 0;
 }
 
-int drmSyncobjDestroy(int fd, uint32_t handle)
+drm_public int drmSyncobjDestroy(int fd, uint32_t handle)
 {
     struct drm_syncobj_destroy args;
 
@@ -4378,7 +4339,7 @@ int drmSyncobjDestroy(int fd, uint32_t h
     return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_DESTROY, &args);
 }
 
-int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd)
+drm_public int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd)
 {
     struct drm_syncobj_handle args;
     int ret;
@@ -4393,7 +4354,7 @@ int drmSyncobjHandleToFD(int fd, uint32_
     return 0;
 }
 
-int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle)
+drm_public int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle)
 {
     struct drm_syncobj_handle args;
     int ret;
@@ -4408,7 +4369,8 @@ int drmSyncobjFDToHandle(int fd, int obj
     return 0;
 }
 
-int drmSyncobjImportSyncFile(int fd, uint32_t handle, int sync_file_fd)
+drm_public int drmSyncobjImportSyncFile(int fd, uint32_t handle,
+                                        int sync_file_fd)
 {
     struct drm_syncobj_handle args;
 
@@ -4419,7 +4381,8 @@ int drmSyncobjImportSyncFile(int fd, uin
     return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args);
 }
 
-int drmSyncobjExportSyncFile(int fd, uint32_t handle, int *sync_file_fd)
+drm_public int drmSyncobjExportSyncFile(int fd, uint32_t handle,
+                                        int *sync_file_fd)
 {
     struct drm_syncobj_handle args;
     int ret;
@@ -4435,9 +4398,9 @@ int drmSyncobjExportSyncFile(int fd, uin
     return 0;
 }
 
-int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles,
-                   int64_t timeout_nsec, unsigned flags,
-                   uint32_t *first_signaled)
+drm_public int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles,
+                              int64_t timeout_nsec, unsigned flags,
+                              uint32_t *first_signaled)
 {
     struct drm_syncobj_wait args;
     int ret;
@@ -4457,7 +4420,8 @@ int drmSyncobjWait(int fd, uint32_t *han
     return ret;
 }
 
-int drmSyncobjReset(int fd, const uint32_t *handles, uint32_t handle_count)
+drm_public int drmSyncobjReset(int fd, const uint32_t *handles,
+                               uint32_t handle_count)
 {
     struct drm_syncobj_array args;
     int ret;
@@ -4470,7 +4434,8 @@ int drmSyncobjReset(int fd, const uint32
     return ret;
 }
 
-int drmSyncobjSignal(int fd, const uint32_t *handles, uint32_t handle_count)
+drm_public int drmSyncobjSignal(int fd, const uint32_t *handles,
+                                uint32_t handle_count)
 {
     struct drm_syncobj_array args;
     int ret;

Index: xsrc/external/mit/libdrm/dist/xf86drmMode.c
diff -u xsrc/external/mit/libdrm/dist/xf86drmMode.c:1.13 xsrc/external/mit/libdrm/dist/xf86drmMode.c:1.14
--- xsrc/external/mit/libdrm/dist/xf86drmMode.c:1.13	Wed Mar 14 07:19:26 2018
+++ xsrc/external/mit/libdrm/dist/xf86drmMode.c	Thu Jan 10 08:59:43 2019
@@ -38,10 +38,6 @@
  * platforms find which headers to include to get uint32_t
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <limits.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -52,6 +48,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 
+#include "libdrm_macros.h"
 #include "xf86drmMode.h"
 #include "xf86drm.h"
 #include <drm.h>
@@ -96,7 +93,7 @@ static void* drmAllocCpy(char *array, in
  * A couple of free functions.
  */
 
-void drmModeFreeModeInfo(drmModeModeInfoPtr ptr)
+drm_public void drmModeFreeModeInfo(drmModeModeInfoPtr ptr)
 {
 	if (!ptr)
 		return;
@@ -104,7 +101,7 @@ void drmModeFreeModeInfo(drmModeModeInfo
 	drmFree(ptr);
 }
 
-void drmModeFreeResources(drmModeResPtr ptr)
+drm_public void drmModeFreeResources(drmModeResPtr ptr)
 {
 	if (!ptr)
 		return;
@@ -116,7 +113,7 @@ void drmModeFreeResources(drmModeResPtr 
 	drmFree(ptr);
 }
 
-void drmModeFreeFB(drmModeFBPtr ptr)
+drm_public void drmModeFreeFB(drmModeFBPtr ptr)
 {
 	if (!ptr)
 		return;
@@ -125,7 +122,7 @@ void drmModeFreeFB(drmModeFBPtr ptr)
 	drmFree(ptr);
 }
 
-void drmModeFreeCrtc(drmModeCrtcPtr ptr)
+drm_public void drmModeFreeCrtc(drmModeCrtcPtr ptr)
 {
 	if (!ptr)
 		return;
@@ -133,7 +130,7 @@ void drmModeFreeCrtc(drmModeCrtcPtr ptr)
 	drmFree(ptr);
 }
 
-void drmModeFreeConnector(drmModeConnectorPtr ptr)
+drm_public void drmModeFreeConnector(drmModeConnectorPtr ptr)
 {
 	if (!ptr)
 		return;
@@ -145,7 +142,7 @@ void drmModeFreeConnector(drmModeConnect
 	drmFree(ptr);
 }
 
-void drmModeFreeEncoder(drmModeEncoderPtr ptr)
+drm_public void drmModeFreeEncoder(drmModeEncoderPtr ptr)
 {
 	drmFree(ptr);
 }
@@ -154,7 +151,7 @@ void drmModeFreeEncoder(drmModeEncoderPt
  * ModeSetting functions.
  */
 
-drmModeResPtr drmModeGetResources(int fd)
+drm_public drmModeResPtr drmModeGetResources(int fd)
 {
 	struct drm_mode_card_res res, counts;
 	drmModeResPtr r = 0;
@@ -248,9 +245,10 @@ err_allocs:
 	return r;
 }
 
-int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
-		 uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
-		 uint32_t *buf_id)
+
+drm_public int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
+                            uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
+                            uint32_t *buf_id)
 {
 	struct drm_mode_fb_cmd f;
 	int ret;
@@ -270,10 +268,10 @@ int drmModeAddFB(int fd, uint32_t width,
 	return 0;
 }
 
-int drmModeAddFB2WithModifiers(int fd, uint32_t width, uint32_t height,
-                               uint32_t pixel_format, const uint32_t bo_handles[4],
-                               const uint32_t pitches[4], const uint32_t offsets[4],
-                               const uint64_t modifier[4], uint32_t *buf_id, uint32_t flags)
+drm_public int drmModeAddFB2WithModifiers(int fd, uint32_t width,
+		uint32_t height, uint32_t pixel_format, const uint32_t bo_handles[4],
+		const uint32_t pitches[4], const uint32_t offsets[4],
+		const uint64_t modifier[4], uint32_t *buf_id, uint32_t flags)
 {
 	struct drm_mode_fb_cmd2 f;
 	int ret;
@@ -296,10 +294,10 @@ int drmModeAddFB2WithModifiers(int fd, u
 	return 0;
 }
 
-int drmModeAddFB2(int fd, uint32_t width, uint32_t height,
-                  uint32_t pixel_format, const uint32_t bo_handles[4],
-                  const uint32_t pitches[4], const uint32_t offsets[4],
-                  uint32_t *buf_id, uint32_t flags)
+drm_public int drmModeAddFB2(int fd, uint32_t width, uint32_t height,
+		uint32_t pixel_format, const uint32_t bo_handles[4],
+		const uint32_t pitches[4], const uint32_t offsets[4],
+		uint32_t *buf_id, uint32_t flags)
 {
 	return drmModeAddFB2WithModifiers(fd, width, height,
 					  pixel_format, bo_handles,
@@ -307,12 +305,12 @@ int drmModeAddFB2(int fd, uint32_t width
 					  buf_id, flags);
 }
 
-int drmModeRmFB(int fd, uint32_t bufferId)
+drm_public int drmModeRmFB(int fd, uint32_t bufferId)
 {
 	return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
 }
 
-drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
+drm_public drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
 {
 	struct drm_mode_fb_cmd info;
 	drmModeFBPtr r;
@@ -337,7 +335,7 @@ drmModeFBPtr drmModeGetFB(int fd, uint32
 	return r;
 }
 
-int drmModeDirtyFB(int fd, uint32_t bufferId,
+drm_public int drmModeDirtyFB(int fd, uint32_t bufferId,
 		   drmModeClipPtr clips, uint32_t num_clips)
 {
 	struct drm_mode_fb_dirty_cmd dirty;
@@ -354,7 +352,7 @@ int drmModeDirtyFB(int fd, uint32_t buff
  * Crtc functions
  */
 
-drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
+drm_public drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
 {
 	struct drm_mode_crtc crtc;
 	drmModeCrtcPtr r;
@@ -386,7 +384,7 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, ui
 	return r;
 }
 
-int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
+drm_public int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
 		   uint32_t x, uint32_t y, uint32_t *connectors, int count,
 		   drmModeModeInfoPtr mode)
 {
@@ -411,7 +409,8 @@ int drmModeSetCrtc(int fd, uint32_t crtc
  * Cursor manipulation
  */
 
-int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height)
+drm_public int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle,
+								uint32_t width, uint32_t height)
 {
 	struct drm_mode_cursor arg;
 
@@ -425,7 +424,9 @@ int drmModeSetCursor(int fd, uint32_t cr
 	return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg);
 }
 
-int drmModeSetCursor2(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height, int32_t hot_x, int32_t hot_y)
+drm_public int drmModeSetCursor2(int fd, uint32_t crtcId, uint32_t bo_handle,
+								 uint32_t width, uint32_t height, int32_t hot_x,
+								 int32_t hot_y)
 {
 	struct drm_mode_cursor2 arg;
 
@@ -441,7 +442,7 @@ int drmModeSetCursor2(int fd, uint32_t c
 	return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR2, &arg);
 }
 
-int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y)
+drm_public int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y)
 {
 	struct drm_mode_cursor arg;
 
@@ -457,7 +458,7 @@ int drmModeMoveCursor(int fd, uint32_t c
 /*
  * Encoder get
  */
-drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id)
+drm_public drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id)
 {
 	struct drm_mode_get_encoder enc;
 	drmModeEncoderPtr r = NULL;
@@ -589,17 +590,17 @@ err_allocs:
 	return r;
 }
 
-drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
+drm_public drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
 {
 	return _drmModeGetConnector(fd, connector_id, 1);
 }
 
-drmModeConnectorPtr drmModeGetConnectorCurrent(int fd, uint32_t connector_id)
+drm_public drmModeConnectorPtr drmModeGetConnectorCurrent(int fd, uint32_t connector_id)
 {
 	return _drmModeGetConnector(fd, connector_id, 0);
 }
 
-int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info)
+drm_public int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info)
 {
 	struct drm_mode_mode_cmd res;
 
@@ -610,7 +611,7 @@ int drmModeAttachMode(int fd, uint32_t c
 	return DRM_IOCTL(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
 }
 
-int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info)
+drm_public int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info)
 {
 	struct drm_mode_mode_cmd res;
 
@@ -621,7 +622,7 @@ int drmModeDetachMode(int fd, uint32_t c
 	return DRM_IOCTL(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
 }
 
-drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
+drm_public drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
 {
 	struct drm_mode_get_property prop;
 	drmModePropertyPtr r;
@@ -675,7 +676,7 @@ err_allocs:
 	return r;
 }
 
-void drmModeFreeProperty(drmModePropertyPtr ptr)
+drm_public void drmModeFreeProperty(drmModePropertyPtr ptr)
 {
 	if (!ptr)
 		return;
@@ -685,7 +686,8 @@ void drmModeFreeProperty(drmModeProperty
 	drmFree(ptr);
 }
 
-drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id)
+drm_public drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd,
+														 uint32_t blob_id)
 {
 	struct drm_mode_get_blob blob;
 	drmModePropertyBlobPtr r;
@@ -716,7 +718,7 @@ err_allocs:
 	return r;
 }
 
-void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
+drm_public void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
 {
 	if (!ptr)
 		return;
@@ -725,8 +727,9 @@ void drmModeFreePropertyBlob(drmModeProp
 	drmFree(ptr);
 }
 
-int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
-			     uint64_t value)
+drm_public int drmModeConnectorSetProperty(int fd, uint32_t connector_id,
+										   uint32_t property_id,
+										   uint64_t value)
 {
 	struct drm_mode_connector_set_property osp;
 
@@ -744,7 +747,7 @@ int drmModeConnectorSetProperty(int fd, 
  *  -EINVAL or invalid bus id
  *  -ENOSYS if no modesetting support
 */
-int drmCheckModesettingSupported(const char *busid)
+drm_public int drmCheckModesettingSupported(const char *busid)
 {
 #if defined (__linux__)
 	char pci_dev_dir[1024];
@@ -831,21 +834,7 @@ int drmCheckModesettingSupported(const c
 	}
 #elif defined(__DragonFly__)
 	return 0;
-#else
-	int fd;
-	static const struct drm_mode_card_res zero_res;
-	struct drm_mode_card_res res = zero_res;
-	int ret;
- 
-	fd = drmOpen(NULL, busid);
-	if (fd == -1)
-		return -EINVAL;
-	ret = drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res);
-	drmClose(fd);
-	if (ret == 0)
-		return 0;
-#endif
-#ifdef __OpenBSD__
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
 	int	fd;
 	struct drm_mode_card_res res;
 	drmModeResPtr r = 0;
@@ -866,8 +855,9 @@ int drmCheckModesettingSupported(const c
 	return -ENOSYS;
 }
 
-int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
-			uint16_t *red, uint16_t *green, uint16_t *blue)
+drm_public int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
+								   uint16_t *red, uint16_t *green,
+								   uint16_t *blue)
 {
 	struct drm_mode_crtc_lut l;
 
@@ -881,8 +871,9 @@ int drmModeCrtcGetGamma(int fd, uint32_t
 	return DRM_IOCTL(fd, DRM_IOCTL_MODE_GETGAMMA, &l);
 }
 
-int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
-			uint16_t *red, uint16_t *green, uint16_t *blue)
+drm_public int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
+								   uint16_t *red, uint16_t *green,
+								   uint16_t *blue)
 {
 	struct drm_mode_crtc_lut l;
 
@@ -896,7 +887,7 @@ int drmModeCrtcSetGamma(int fd, uint32_t
 	return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETGAMMA, &l);
 }
 
-int drmHandleEvent(int fd, drmEventContextPtr evctx)
+drm_public int drmHandleEvent(int fd, drmEventContextPtr evctx)
 {
 	char buffer[1024];
 	int len, i;
@@ -964,7 +955,7 @@ int drmHandleEvent(int fd, drmEventConte
 	return 0;
 }
 
-int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id,
+drm_public int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id,
 		    uint32_t flags, void *user_data)
 {
 	struct drm_mode_crtc_page_flip flip;
@@ -978,7 +969,7 @@ int drmModePageFlip(int fd, uint32_t crt
 	return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip);
 }
 
-int drmModePageFlipTarget(int fd, uint32_t crtc_id, uint32_t fb_id,
+drm_public int drmModePageFlipTarget(int fd, uint32_t crtc_id, uint32_t fb_id,
 			  uint32_t flags, void *user_data,
 			  uint32_t target_vblank)
 {
@@ -994,7 +985,7 @@ int drmModePageFlipTarget(int fd, uint32
 	return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip_target);
 }
 
-int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id,
+drm_public int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id,
 		    uint32_t fb_id, uint32_t flags,
 		    uint32_t crtc_x, uint32_t crtc_y,
 		    uint32_t crtc_w, uint32_t crtc_h,
@@ -1020,7 +1011,7 @@ int drmModeSetPlane(int fd, uint32_t pla
 	return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPLANE, &s);
 }
 
-drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id)
+drm_public drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id)
 {
 	struct drm_mode_get_plane ovr, counts;
 	drmModePlanePtr r = 0;
@@ -1071,7 +1062,7 @@ err_allocs:
 	return r;
 }
 
-void drmModeFreePlane(drmModePlanePtr ptr)
+drm_public void drmModeFreePlane(drmModePlanePtr ptr)
 {
 	if (!ptr)
 		return;
@@ -1080,7 +1071,7 @@ void drmModeFreePlane(drmModePlanePtr pt
 	drmFree(ptr);
 }
 
-drmModePlaneResPtr drmModeGetPlaneResources(int fd)
+drm_public drmModePlaneResPtr drmModeGetPlaneResources(int fd)
 {
 	struct drm_mode_get_plane_res res, counts;
 	drmModePlaneResPtr r = 0;
@@ -1125,7 +1116,7 @@ err_allocs:
 	return r;
 }
 
-void drmModeFreePlaneResources(drmModePlaneResPtr ptr)
+drm_public void drmModeFreePlaneResources(drmModePlaneResPtr ptr)
 {
 	if (!ptr)
 		return;
@@ -1134,7 +1125,7 @@ void drmModeFreePlaneResources(drmModePl
 	drmFree(ptr);
 }
 
-drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd,
+drm_public drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd,
 						      uint32_t object_id,
 						      uint32_t object_type)
 {
@@ -1195,7 +1186,7 @@ err_allocs:
 	return ret;
 }
 
-void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr)
+drm_public void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr)
 {
 	if (!ptr)
 		return;
@@ -1204,7 +1195,7 @@ void drmModeFreeObjectProperties(drmMode
 	drmFree(ptr);
 }
 
-int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type,
+drm_public int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type,
 			     uint32_t property_id, uint64_t value)
 {
 	struct drm_mode_obj_set_property prop;
@@ -1232,7 +1223,7 @@ struct _drmModeAtomicReq {
 	drmModeAtomicReqItemPtr items;
 };
 
-drmModeAtomicReqPtr drmModeAtomicAlloc(void)
+drm_public drmModeAtomicReqPtr drmModeAtomicAlloc(void)
 {
 	drmModeAtomicReqPtr req;
 
@@ -1247,7 +1238,7 @@ drmModeAtomicReqPtr drmModeAtomicAlloc(v
 	return req;
 }
 
-drmModeAtomicReqPtr drmModeAtomicDuplicate(drmModeAtomicReqPtr old)
+drm_public drmModeAtomicReqPtr drmModeAtomicDuplicate(drmModeAtomicReqPtr old)
 {
 	drmModeAtomicReqPtr new;
 
@@ -1276,7 +1267,8 @@ drmModeAtomicReqPtr drmModeAtomicDuplica
 	return new;
 }
 
-int drmModeAtomicMerge(drmModeAtomicReqPtr base, drmModeAtomicReqPtr augment)
+drm_public int drmModeAtomicMerge(drmModeAtomicReqPtr base,
+                                  drmModeAtomicReqPtr augment)
 {
 	if (!base)
 		return -EINVAL;
@@ -1305,27 +1297,30 @@ int drmModeAtomicMerge(drmModeAtomicReqP
 	return 0;
 }
 
-int drmModeAtomicGetCursor(drmModeAtomicReqPtr req)
+drm_public int drmModeAtomicGetCursor(drmModeAtomicReqPtr req)
 {
 	if (!req)
 		return -EINVAL;
 	return req->cursor;
 }
 
-void drmModeAtomicSetCursor(drmModeAtomicReqPtr req, int cursor)
+drm_public void drmModeAtomicSetCursor(drmModeAtomicReqPtr req, int cursor)
 {
 	if (req)
 		req->cursor = cursor;
 }
 
-int drmModeAtomicAddProperty(drmModeAtomicReqPtr req,
-			     uint32_t object_id,
-			     uint32_t property_id,
-			     uint64_t value)
+drm_public int drmModeAtomicAddProperty(drmModeAtomicReqPtr req,
+                                        uint32_t object_id,
+                                        uint32_t property_id,
+                                        uint64_t value)
 {
 	if (!req)
 		return -EINVAL;
 
+	if (object_id == 0 || property_id == 0)
+		return -EINVAL;
+
 	if (req->cursor >= req->size_items) {
 		drmModeAtomicReqItemPtr new;
 
@@ -1346,7 +1341,7 @@ int drmModeAtomicAddProperty(drmModeAtom
 	return req->cursor;
 }
 
-void drmModeAtomicFree(drmModeAtomicReqPtr req)
+drm_public void drmModeAtomicFree(drmModeAtomicReqPtr req)
 {
 	if (!req)
 		return;
@@ -1369,8 +1364,8 @@ static int sort_req_list(const void *mis
 		return second->property_id - first->property_id;
 }
 
-int drmModeAtomicCommit(int fd, drmModeAtomicReqPtr req, uint32_t flags,
-			void *user_data)
+drm_public int drmModeAtomicCommit(int fd, drmModeAtomicReqPtr req,
+                                   uint32_t flags, void *user_data)
 {
 	drmModeAtomicReqPtr sorted;
 	struct drm_mode_atomic atomic;
@@ -1474,8 +1469,9 @@ out:
 	return ret;
 }
 
-int
-drmModeCreatePropertyBlob(int fd, const void *data, size_t length, uint32_t *id)
+drm_public int
+drmModeCreatePropertyBlob(int fd, const void *data, size_t length,
+                                     uint32_t *id)
 {
 	struct drm_mode_create_blob create;
 	int ret;
@@ -1498,7 +1494,7 @@ drmModeCreatePropertyBlob(int fd, const 
 	return 0;
 }
 
-int
+drm_public int
 drmModeDestroyPropertyBlob(int fd, uint32_t id)
 {
 	struct drm_mode_destroy_blob destroy;
@@ -1508,8 +1504,9 @@ drmModeDestroyPropertyBlob(int fd, uint3
 	return DRM_IOCTL(fd, DRM_IOCTL_MODE_DESTROYPROPBLOB, &destroy);
 }
 
-int
-drmModeCreateLease(int fd, const uint32_t *objects, int num_objects, int flags, uint32_t *lessee_id)
+drm_public int
+drmModeCreateLease(int fd, const uint32_t *objects, int num_objects, int flags,
+                   uint32_t *lessee_id)
 {
 	struct drm_mode_create_lease create;
 	int ret;
@@ -1527,7 +1524,7 @@ drmModeCreateLease(int fd, const uint32_
 	return -errno;
 }
 
-drmModeLesseeListPtr
+drm_public drmModeLesseeListPtr
 drmModeListLessees(int fd)
 {
 	struct drm_mode_list_lessees list;
@@ -1554,7 +1551,7 @@ drmModeListLessees(int fd)
 	return ret;
 }
 
-drmModeObjectListPtr
+drm_public drmModeObjectListPtr
 drmModeGetLease(int fd)
 {
 	struct drm_mode_get_lease get;
@@ -1581,7 +1578,7 @@ drmModeGetLease(int fd)
 	return ret;
 }
 
-int
+drm_public int
 drmModeRevokeLease(int fd, uint32_t lessee_id)
 {
 	struct drm_mode_revoke_lease revoke;

Index: xsrc/external/mit/libdrm/dist/include/drm/drm.h
diff -u xsrc/external/mit/libdrm/dist/include/drm/drm.h:1.10 xsrc/external/mit/libdrm/dist/include/drm/drm.h:1.11
--- xsrc/external/mit/libdrm/dist/include/drm/drm.h:1.10	Sun Dec  2 00:42:04 2018
+++ xsrc/external/mit/libdrm/dist/include/drm/drm.h	Thu Jan 10 08:59:43 2019
@@ -677,6 +677,22 @@ struct drm_get_cap {
  */
 #define DRM_CLIENT_CAP_ATOMIC	3
 
+/**
+ * DRM_CLIENT_CAP_ASPECT_RATIO
+ *
+ * If set to 1, the DRM core will provide aspect ratio information in modes.
+ */
+#define DRM_CLIENT_CAP_ASPECT_RATIO    4
+
+/**
+ * DRM_CLIENT_CAP_WRITEBACK_CONNECTORS
+ *
+ * If set to 1, the DRM core will expose special connectors to be used for
+ * writing back to memory the scene setup in the commit. Depends on client
+ * also supporting DRM_CLIENT_CAP_ATOMIC
+ */
+#define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS	5
+
 /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
 struct drm_set_client_cap {
 	__u64 capability;

Index: xsrc/external/mit/libdrm/dist/include/drm/i915_drm.h
diff -u xsrc/external/mit/libdrm/dist/include/drm/i915_drm.h:1.5 xsrc/external/mit/libdrm/dist/include/drm/i915_drm.h:1.6
--- xsrc/external/mit/libdrm/dist/include/drm/i915_drm.h:1.5	Sat Mar  4 23:22:48 2017
+++ xsrc/external/mit/libdrm/dist/include/drm/i915_drm.h	Thu Jan 10 08:59:43 2019
@@ -86,6 +86,62 @@ enum i915_mocs_table_index {
 	I915_MOCS_CACHED,
 };
 
+/*
+ * Different engines serve different roles, and there may be more than one
+ * engine serving each role. enum drm_i915_gem_engine_class provides a
+ * classification of the role of the engine, which may be used when requesting
+ * operations to be performed on a certain subset of engines, or for providing
+ * information about that group.
+ */
+enum drm_i915_gem_engine_class {
+	I915_ENGINE_CLASS_RENDER	= 0,
+	I915_ENGINE_CLASS_COPY		= 1,
+	I915_ENGINE_CLASS_VIDEO		= 2,
+	I915_ENGINE_CLASS_VIDEO_ENHANCE	= 3,
+
+	I915_ENGINE_CLASS_INVALID	= -1
+};
+
+/**
+ * DOC: perf_events exposed by i915 through /sys/bus/event_sources/drivers/i915
+ *
+ */
+
+enum drm_i915_pmu_engine_sample {
+	I915_SAMPLE_BUSY = 0,
+	I915_SAMPLE_WAIT = 1,
+	I915_SAMPLE_SEMA = 2
+};
+
+#define I915_PMU_SAMPLE_BITS (4)
+#define I915_PMU_SAMPLE_MASK (0xf)
+#define I915_PMU_SAMPLE_INSTANCE_BITS (8)
+#define I915_PMU_CLASS_SHIFT \
+	(I915_PMU_SAMPLE_BITS + I915_PMU_SAMPLE_INSTANCE_BITS)
+
+#define __I915_PMU_ENGINE(class, instance, sample) \
+	((class) << I915_PMU_CLASS_SHIFT | \
+	(instance) << I915_PMU_SAMPLE_BITS | \
+	(sample))
+
+#define I915_PMU_ENGINE_BUSY(class, instance) \
+	__I915_PMU_ENGINE(class, instance, I915_SAMPLE_BUSY)
+
+#define I915_PMU_ENGINE_WAIT(class, instance) \
+	__I915_PMU_ENGINE(class, instance, I915_SAMPLE_WAIT)
+
+#define I915_PMU_ENGINE_SEMA(class, instance) \
+	__I915_PMU_ENGINE(class, instance, I915_SAMPLE_SEMA)
+
+#define __I915_PMU_OTHER(x) (__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x))
+
+#define I915_PMU_ACTUAL_FREQUENCY	__I915_PMU_OTHER(0)
+#define I915_PMU_REQUESTED_FREQUENCY	__I915_PMU_OTHER(1)
+#define I915_PMU_INTERRUPTS		__I915_PMU_OTHER(2)
+#define I915_PMU_RC6_RESIDENCY		__I915_PMU_OTHER(3)
+
+#define I915_PMU_LAST I915_PMU_RC6_RESIDENCY
+
 /* Each region is a minimum of 16k, and there are at most 255 of them.
  */
 #define I915_NR_TEX_REGIONS 255	/* table size 2k - maximum due to use
@@ -260,6 +316,9 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_GEM_CONTEXT_GETPARAM	0x34
 #define DRM_I915_GEM_CONTEXT_SETPARAM	0x35
 #define DRM_I915_PERF_OPEN		0x36
+#define DRM_I915_PERF_ADD_CONFIG	0x37
+#define DRM_I915_PERF_REMOVE_CONFIG	0x38
+#define DRM_I915_QUERY			0x39
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -315,6 +374,9 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param)
 #define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param)
 #define DRM_IOCTL_I915_PERF_OPEN	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
+#define DRM_IOCTL_I915_PERF_ADD_CONFIG	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
+#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
+#define DRM_IOCTL_I915_QUERY			DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -393,10 +455,20 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_MIN_EU_IN_POOL	 39
 #define I915_PARAM_MMAP_GTT_VERSION	 40
 
-/* Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution
+/*
+ * Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution
  * priorities and the driver will attempt to execute batches in priority order.
+ * The param returns a capability bitmask, nonzero implies that the scheduler
+ * is enabled, with different features present according to the mask.
+ *
+ * The initial priority for each batch is supplied by the context and is
+ * controlled via I915_CONTEXT_PARAM_PRIORITY.
  */
 #define I915_PARAM_HAS_SCHEDULER	 41
+#define   I915_SCHEDULER_CAP_ENABLED	(1ul << 0)
+#define   I915_SCHEDULER_CAP_PRIORITY	(1ul << 1)
+#define   I915_SCHEDULER_CAP_PREEMPTION	(1ul << 2)
+
 #define I915_PARAM_HUC_STATUS		 42
 
 /* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to opt-out of
@@ -412,6 +484,73 @@ typedef struct drm_i915_irq_wait {
  */
 #define I915_PARAM_HAS_EXEC_FENCE	 44
 
+/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to capture
+ * user specified bufffers for post-mortem debugging of GPU hangs. See
+ * EXEC_OBJECT_CAPTURE.
+ */
+#define I915_PARAM_HAS_EXEC_CAPTURE	 45
+
+#define I915_PARAM_SLICE_MASK		 46
+
+/* Assuming it's uniform for each slice, this queries the mask of subslices
+ * per-slice for this system.
+ */
+#define I915_PARAM_SUBSLICE_MASK	 47
+
+/*
+ * Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying the batch buffer
+ * as the first execobject as opposed to the last. See I915_EXEC_BATCH_FIRST.
+ */
+#define I915_PARAM_HAS_EXEC_BATCH_FIRST	 48
+
+/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of
+ * drm_i915_gem_exec_fence structures.  See I915_EXEC_FENCE_ARRAY.
+ */
+#define I915_PARAM_HAS_EXEC_FENCE_ARRAY  49
+
+/*
+ * Query whether every context (both per-file default and user created) is
+ * isolated (insofar as HW supports). If this parameter is not true, then
+ * freshly created contexts may inherit values from an existing context,
+ * rather than default HW values. If true, it also ensures (insofar as HW
+ * supports) that all state set by this context will not leak to any other
+ * context.
+ *
+ * As not every engine across every gen support contexts, the returned
+ * value reports the support of context isolation for individual engines by
+ * returning a bitmask of each engine class set to true if that class supports
+ * isolation.
+ */
+#define I915_PARAM_HAS_CONTEXT_ISOLATION 50
+
+/* Frequency of the command streamer timestamps given by the *_TIMESTAMP
+ * registers. This used to be fixed per platform but from CNL onwards, this
+ * might vary depending on the parts.
+ */
+#define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51
+
+/*
+ * Once upon a time we supposed that writes through the GGTT would be
+ * immediately in physical memory (once flushed out of the CPU path). However,
+ * on a few different processors and chipsets, this is not necessarily the case
+ * as the writes appear to be buffered internally. Thus a read of the backing
+ * storage (physical memory) via a different path (with different physical tags
+ * to the indirect write via the GGTT) will see stale values from before
+ * the GGTT write. Inside the kernel, we can for the most part keep track of
+ * the different read/write domains in use (e.g. set-domain), but the assumption
+ * of coherency is baked into the ABI, hence reporting its true state in this
+ * parameter.
+ *
+ * Reports true when writes via mmap_gtt are immediately visible following an
+ * lfence to flush the WCB.
+ *
+ * Reports false when writes via mmap_gtt are indeterminately delayed in an in
+ * internal buffer and are _not_ immediately visible to third parties accessing
+ * directly via mmap_cpu/mmap_wc. Use of mmap_gtt as part of an IPC
+ * communications channel when reporting false is strongly disadvised.
+ */
+#define I915_PARAM_MMAP_GTT_COHERENT	52
+
 typedef struct drm_i915_getparam {
 	__s32 param;
 	/*
@@ -666,6 +805,8 @@ struct drm_i915_gem_relocation_entry {
 #define I915_GEM_DOMAIN_VERTEX		0x00000020
 /** GTT domain - aperture and scanout */
 #define I915_GEM_DOMAIN_GTT		0x00000040
+/** WC domain - uncached access */
+#define I915_GEM_DOMAIN_WC		0x00000080
 /** @} */
 
 struct drm_i915_gem_exec_object {
@@ -773,8 +914,15 @@ struct drm_i915_gem_exec_object2 {
  * I915_PARAM_HAS_EXEC_FENCE to order execbufs and execute them asynchronously.
  */
 #define EXEC_OBJECT_ASYNC		(1<<6)
+/* Request that the contents of this execobject be copied into the error
+ * state upon a GPU hang involving this batch for post-mortem debugging.
+ * These buffers are recorded in no particular order as "user" in
+ * /sys/class/drm/cardN/error. Query I915_PARAM_HAS_EXEC_CAPTURE to see
+ * if the kernel supports this flag.
+ */
+#define EXEC_OBJECT_CAPTURE		(1<<7)
 /* All remaining bits are MBZ and RESERVED FOR FUTURE USE */
-#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_ASYNC<<1)
+#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_CAPTURE<<1)
 	__u64 flags;
 
 	union {
@@ -784,6 +932,18 @@ struct drm_i915_gem_exec_object2 {
 	__u64 rsvd2;
 };
 
+struct drm_i915_gem_exec_fence {
+	/**
+	 * User's handle for a drm_syncobj to wait on or signal.
+	 */
+	__u32 handle;
+
+#define I915_EXEC_FENCE_WAIT            (1<<0)
+#define I915_EXEC_FENCE_SIGNAL          (1<<1)
+#define __I915_EXEC_FENCE_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SIGNAL << 1))
+	__u32 flags;
+};
+
 struct drm_i915_gem_execbuffer2 {
 	/**
 	 * List of gem_exec_object2 structs
@@ -798,7 +958,11 @@ struct drm_i915_gem_execbuffer2 {
 	__u32 DR1;
 	__u32 DR4;
 	__u32 num_cliprects;
-	/** This is a struct drm_clip_rect *cliprects */
+	/**
+	 * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY
+	 * is not set.  If I915_EXEC_FENCE_ARRAY is set, then this is a
+	 * struct drm_i915_gem_exec_fence *fences.
+	 */
 	__u64 cliprects_ptr;
 #define I915_EXEC_RING_MASK              (7<<0)
 #define I915_EXEC_DEFAULT                (0<<0)
@@ -889,7 +1053,24 @@ struct drm_i915_gem_execbuffer2 {
  */
 #define I915_EXEC_FENCE_OUT		(1<<17)
 
-#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_OUT<<1))
+/*
+ * Traditionally the execbuf ioctl has only considered the final element in
+ * the execobject[] to be the executable batch. Often though, the client
+ * will known the batch object prior to construction and being able to place
+ * it into the execobject[] array first can simplify the relocation tracking.
+ * Setting I915_EXEC_BATCH_FIRST tells execbuf to use element 0 of the
+ * execobject[] as the * batch instead (the default is to use the last
+ * element).
+ */
+#define I915_EXEC_BATCH_FIRST		(1<<18)
+
+/* Setting I915_FENCE_ARRAY implies that num_cliprects and cliprects_ptr
+ * define an array of i915_gem_exec_fence structures which specify a set of
+ * dma fences to wait upon or signal.
+ */
+#define I915_EXEC_FENCE_ARRAY   (1<<19)
+
+#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1))
 
 #define I915_EXEC_CONTEXT_ID_MASK	(0xffffffff)
 #define i915_execbuffer2_set_context_id(eb2, context) \
@@ -1201,7 +1382,9 @@ struct drm_intel_overlay_attrs {
  * active on a given plane.
  */
 
-#define I915_SET_COLORKEY_NONE		(1<<0) /* disable color key matching */
+#define I915_SET_COLORKEY_NONE		(1<<0) /* Deprecated. Instead set
+						* flags==0 to disable colorkeying.
+						*/
 #define I915_SET_COLORKEY_DESTINATION	(1<<1)
 #define I915_SET_COLORKEY_SOURCE	(1<<2)
 struct drm_intel_sprite_colorkey {
@@ -1239,14 +1422,16 @@ struct drm_i915_reg_read {
 	 * be specified
 	 */
 	__u64 offset;
+#define I915_REG_READ_8B_WA (1ul << 0)
+
 	__u64 val; /* Return value */
 };
 /* Known registers:
  *
  * Render engine timestamp - 0x2358 + 64bit - gen7+
  * - Note this register returns an invalid value if using the default
- *   single instruction 8byte read, in order to workaround that use
- *   offset (0x2538 | 1) instead.
+ *   single instruction 8byte read, in order to workaround that pass
+ *   flag I915_REG_READ_8B_WA in offset field.
  *
  */
 
@@ -1289,17 +1474,26 @@ struct drm_i915_gem_context_param {
 #define I915_CONTEXT_PARAM_GTT_SIZE	0x3
 #define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE	0x4
 #define I915_CONTEXT_PARAM_BANNABLE	0x5
+#define I915_CONTEXT_PARAM_PRIORITY	0x6
+#define   I915_CONTEXT_MAX_USER_PRIORITY	1023 /* inclusive */
+#define   I915_CONTEXT_DEFAULT_PRIORITY		0
+#define   I915_CONTEXT_MIN_USER_PRIORITY	-1023 /* inclusive */
 	__u64 value;
 };
 
 enum drm_i915_oa_format {
-	I915_OA_FORMAT_A13 = 1,
-	I915_OA_FORMAT_A29,
-	I915_OA_FORMAT_A13_B8_C8,
-	I915_OA_FORMAT_B4_C8,
-	I915_OA_FORMAT_A45_B8_C8,
-	I915_OA_FORMAT_B4_C8_A16,
-	I915_OA_FORMAT_C4_B8,
+	I915_OA_FORMAT_A13 = 1,	    /* HSW only */
+	I915_OA_FORMAT_A29,	    /* HSW only */
+	I915_OA_FORMAT_A13_B8_C8,   /* HSW only */
+	I915_OA_FORMAT_B4_C8,	    /* HSW only */
+	I915_OA_FORMAT_A45_B8_C8,   /* HSW only */
+	I915_OA_FORMAT_B4_C8_A16,   /* HSW only */
+	I915_OA_FORMAT_C4_B8,	    /* HSW+ */
+
+	/* Gen8+ */
+	I915_OA_FORMAT_A12,
+	I915_OA_FORMAT_A12_B8_C8,
+	I915_OA_FORMAT_A32u40_A4u32_B8_C8,
 
 	I915_OA_FORMAT_MAX	    /* non-ABI */
 };
@@ -1424,6 +1618,127 @@ enum drm_i915_perf_record_type {
 	DRM_I915_PERF_RECORD_MAX /* non-ABI */
 };
 
+/**
+ * Structure to upload perf dynamic configuration into the kernel.
+ */
+struct drm_i915_perf_oa_config {
+	/** String formatted like "%08x-%04x-%04x-%04x-%012x" */
+	char uuid[36];
+
+	__u32 n_mux_regs;
+	__u32 n_boolean_regs;
+	__u32 n_flex_regs;
+
+	/*
+	 * These fields are pointers to tuples of u32 values (register address,
+	 * value). For example the expected length of the buffer pointed by
+	 * mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs).
+	 */
+	__u64 mux_regs_ptr;
+	__u64 boolean_regs_ptr;
+	__u64 flex_regs_ptr;
+};
+
+struct drm_i915_query_item {
+	__u64 query_id;
+#define DRM_I915_QUERY_TOPOLOGY_INFO    1
+
+	/*
+	 * When set to zero by userspace, this is filled with the size of the
+	 * data to be written at the data_ptr pointer. The kernel sets this
+	 * value to a negative value to signal an error on a particular query
+	 * item.
+	 */
+	__s32 length;
+
+	/*
+	 * Unused for now. Must be cleared to zero.
+	 */
+	__u32 flags;
+
+	/*
+	 * Data will be written at the location pointed by data_ptr when the
+	 * value of length matches the length of the data to be written by the
+	 * kernel.
+	 */
+	__u64 data_ptr;
+};
+
+struct drm_i915_query {
+	__u32 num_items;
+
+	/*
+	 * Unused for now. Must be cleared to zero.
+	 */
+	__u32 flags;
+
+	/*
+	 * This points to an array of num_items drm_i915_query_item structures.
+	 */
+	__u64 items_ptr;
+};
+
+/*
+ * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO :
+ *
+ * data: contains the 3 pieces of information :
+ *
+ * - the slice mask with one bit per slice telling whether a slice is
+ *   available. The availability of slice X can be queried with the following
+ *   formula :
+ *
+ *           (data[X / 8] >> (X % 8)) & 1
+ *
+ * - the subslice mask for each slice with one bit per subslice telling
+ *   whether a subslice is available. The availability of subslice Y in slice
+ *   X can be queried with the following formula :
+ *
+ *           (data[subslice_offset +
+ *                 X * subslice_stride +
+ *                 Y / 8] >> (Y % 8)) & 1
+ *
+ * - the EU mask for each subslice in each slice with one bit per EU telling
+ *   whether an EU is available. The availability of EU Z in subslice Y in
+ *   slice X can be queried with the following formula :
+ *
+ *           (data[eu_offset +
+ *                 (X * max_subslices + Y) * eu_stride +
+ *                 Z / 8] >> (Z % 8)) & 1
+ */
+struct drm_i915_query_topology_info {
+	/*
+	 * Unused for now. Must be cleared to zero.
+	 */
+	__u16 flags;
+
+	__u16 max_slices;
+	__u16 max_subslices;
+	__u16 max_eus_per_subslice;
+
+	/*
+	 * Offset in data[] at which the subslice masks are stored.
+	 */
+	__u16 subslice_offset;
+
+	/*
+	 * Stride at which each of the subslice masks for each slice are
+	 * stored.
+	 */
+	__u16 subslice_stride;
+
+	/*
+	 * Offset in data[] at which the EU masks are stored.
+	 */
+	__u16 eu_offset;
+
+	/*
+	 * Stride at which each of the EU masks for each subslice are stored.
+	 */
+	__u16 eu_stride;
+
+	__u8 data[];
+};
+
 #if defined(__cplusplus)
 }
 #endif

Index: xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c
diff -u xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c:1.15 xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c:1.16
--- xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c:1.15	Wed Mar 14 07:19:26 2018
+++ xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c	Thu Jan 10 08:59:43 2019
@@ -34,10 +34,6 @@
  *	    Dave Airlie <[email protected]>
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <xf86drm.h>
 #include <xf86atomic.h>
 #include <fcntl.h>
@@ -1080,7 +1076,7 @@ check_bo_alloc_userptr(drm_intel_bufmgr 
  * This can be used when one application needs to pass a buffer object
  * to another.
  */
-drm_intel_bo *
+drm_public drm_intel_bo *
 drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr,
 				  const char *name,
 				  unsigned int handle)
@@ -1565,7 +1561,7 @@ map_gtt(drm_intel_bo *bo)
 	return 0;
 }
 
-int
+drm_public int
 drm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
@@ -1624,7 +1620,7 @@ drm_intel_gem_bo_map_gtt(drm_intel_bo *b
  * undefined).
  */
 
-int
+drm_public int
 drm_intel_gem_bo_map_unsynchronized(drm_intel_bo *bo)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
@@ -1713,7 +1709,7 @@ static int drm_intel_gem_bo_unmap(drm_in
 	return ret;
 }
 
-int
+drm_public int
 drm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo)
 {
 	return drm_intel_gem_bo_unmap(bo);
@@ -1838,7 +1834,7 @@ drm_intel_gem_bo_wait_rendering(drm_inte
  * Note that some kernels have broken the inifite wait for negative values
  * promise, upgrade to latest stable kernels if this is the case.
  */
-int
+drm_public int
 drm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
@@ -1874,7 +1870,7 @@ drm_intel_gem_bo_wait(drm_intel_bo *bo, 
  * In combination with drm_intel_gem_bo_pin() and manual fence management, we
  * can do tiled pixmaps this way.
  */
-void
+drm_public void
 drm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
@@ -2101,7 +2097,7 @@ drm_intel_gem_bo_emit_reloc_fence(drm_in
 				read_domains, write_domain, true);
 }
 
-int
+drm_public int
 drm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo)
 {
 	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
@@ -2124,7 +2120,7 @@ drm_intel_gem_bo_get_reloc_count(drm_int
  *
  * This also removes all softpinned targets being referenced by the BO.
  */
-void
+drm_public void
 drm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
@@ -2280,7 +2276,7 @@ drm_intel_update_buffer_offsets2 (drm_in
 	}
 }
 
-void
+drm_public void
 drm_intel_gem_bo_aub_dump_bmp(drm_intel_bo *bo,
 			      int x1, int y1, int width, int height,
 			      enum aub_dump_bmp_format format,
@@ -2482,14 +2478,14 @@ drm_intel_gem_bo_mrb_exec2(drm_intel_bo 
 			-1, NULL, flags);
 }
 
-int
+drm_public int
 drm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx,
 			      int used, unsigned int flags)
 {
 	return do_exec2(bo, used, ctx, NULL, 0, 0, -1, NULL, flags);
 }
 
-int
+drm_public int
 drm_intel_gem_bo_fence_exec(drm_intel_bo *bo,
 			    drm_intel_context *ctx,
 			    int used,
@@ -2630,7 +2626,7 @@ drm_intel_gem_bo_set_softpin_offset(drm_
 	return 0;
 }
 
-drm_intel_bo *
+drm_public drm_intel_bo *
 drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int size)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
@@ -2713,7 +2709,7 @@ err:
 	return NULL;
 }
 
-int
+drm_public int
 drm_intel_bo_gem_export_to_prime(drm_intel_bo *bo, int *prime_fd)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
@@ -2765,7 +2761,7 @@ drm_intel_gem_bo_flink(drm_intel_bo *bo,
  * size is only bounded by how many buffers of that size we've managed to have
  * in flight at once.
  */
-void
+drm_public void
 drm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
@@ -2787,7 +2783,7 @@ drm_intel_bufmgr_gem_enable_reuse(drm_in
  * which can be checked using drm_intel_bufmgr_can_disable_implicit_sync,
  * or subsequent execbufs involving the bo will generate EINVAL.
  */
-void
+drm_public void
 drm_intel_gem_bo_disable_implicit_sync(drm_intel_bo *bo)
 {
 	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
@@ -2806,7 +2802,7 @@ drm_intel_gem_bo_disable_implicit_sync(d
  * function can be used to restore the implicit sync before subsequent
  * rendering.
  */
-void
+drm_public void
 drm_intel_gem_bo_enable_implicit_sync(drm_intel_bo *bo)
 {
 	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
@@ -2818,7 +2814,7 @@ drm_intel_gem_bo_enable_implicit_sync(dr
  * Query whether the kernel supports disabling of its implicit synchronisation
  * before execbuf. See drm_intel_gem_bo_disable_implicit_sync()
  */
-int
+drm_public int
 drm_intel_bufmgr_gem_can_disable_implicit_sync(drm_intel_bufmgr *bufmgr)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
@@ -2833,7 +2829,7 @@ drm_intel_bufmgr_gem_can_disable_implici
  * allocation.  If this option is not enabled, all relocs will have fence
  * register allocated.
  */
-void
+drm_public void
 drm_intel_bufmgr_gem_enable_fenced_relocs(drm_intel_bufmgr *bufmgr)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
@@ -3112,7 +3108,7 @@ init_cache_buckets(drm_intel_bufmgr_gem 
 	}
 }
 
-void
+drm_public void
 drm_intel_bufmgr_gem_set_vma_cache_size(drm_intel_bufmgr *bufmgr, int limit)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
@@ -3181,7 +3177,7 @@ get_pci_device_id(drm_intel_bufmgr_gem *
 	return devid;
 }
 
-int
+drm_public int
 drm_intel_bufmgr_gem_get_devid(drm_intel_bufmgr *bufmgr)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
@@ -3195,7 +3191,7 @@ drm_intel_bufmgr_gem_get_devid(drm_intel
  * This function has to be called before drm_intel_bufmgr_gem_set_aub_dump()
  * for it to have any effect.
  */
-void
+drm_public void
 drm_intel_bufmgr_gem_set_aub_filename(drm_intel_bufmgr *bufmgr,
 				      const char *filename)
 {
@@ -3209,7 +3205,7 @@ drm_intel_bufmgr_gem_set_aub_filename(dr
  * You can set up a GTT and upload your objects into the referenced
  * space, then send off batchbuffers and get BMPs out the other end.
  */
-void
+drm_public void
 drm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable)
 {
 	fprintf(stderr, "libdrm aub dumping is deprecated.\n\n"
@@ -3219,7 +3215,7 @@ drm_intel_bufmgr_gem_set_aub_dump(drm_in
 		"See the intel_aubdump man page for more details.\n");
 }
 
-drm_intel_context *
+drm_public drm_intel_context *
 drm_intel_gem_context_create(drm_intel_bufmgr *bufmgr)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
@@ -3246,7 +3242,7 @@ drm_intel_gem_context_create(drm_intel_b
 	return context;
 }
 
-int
+drm_public int
 drm_intel_gem_context_get_id(drm_intel_context *ctx, uint32_t *ctx_id)
 {
 	if (ctx == NULL)
@@ -3257,7 +3253,7 @@ drm_intel_gem_context_get_id(drm_intel_c
 	return 0;
 }
 
-void
+drm_public void
 drm_intel_gem_context_destroy(drm_intel_context *ctx)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem;
@@ -3280,7 +3276,7 @@ drm_intel_gem_context_destroy(drm_intel_
 	free(ctx);
 }
 
-int
+drm_public int
 drm_intel_get_reset_stats(drm_intel_context *ctx,
 			  uint32_t *reset_count,
 			  uint32_t *active,
@@ -3314,7 +3310,7 @@ drm_intel_get_reset_stats(drm_intel_cont
 	return ret;
 }
 
-int
+drm_public int
 drm_intel_reg_read(drm_intel_bufmgr *bufmgr,
 		   uint32_t offset,
 		   uint64_t *result)
@@ -3332,7 +3328,7 @@ drm_intel_reg_read(drm_intel_bufmgr *buf
 	return ret;
 }
 
-int
+drm_public int
 drm_intel_get_subslice_total(int fd, unsigned int *subslice_total)
 {
 	drm_i915_getparam_t gp;
@@ -3348,7 +3344,7 @@ drm_intel_get_subslice_total(int fd, uns
 	return 0;
 }
 
-int
+drm_public int
 drm_intel_get_eu_total(int fd, unsigned int *eu_total)
 {
 	drm_i915_getparam_t gp;
@@ -3364,7 +3360,7 @@ drm_intel_get_eu_total(int fd, unsigned 
 	return 0;
 }
 
-int
+drm_public int
 drm_intel_get_pooled_eu(int fd)
 {
 	drm_i915_getparam_t gp;
@@ -3379,7 +3375,7 @@ drm_intel_get_pooled_eu(int fd)
 	return ret;
 }
 
-int
+drm_public int
 drm_intel_get_min_eu_in_pool(int fd)
 {
 	drm_i915_getparam_t gp;
@@ -3415,8 +3411,7 @@ drm_intel_get_min_eu_in_pool(int fd)
  * default state (no annotations), call this function with a \c count
  * of zero.
  */
-void
-drm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo,
+drm_public void drm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo,
 					 drm_intel_aub_annotation *annotations,
 					 unsigned count)
 {
@@ -3457,7 +3452,7 @@ drm_intel_bufmgr_gem_unref(drm_intel_buf
 	}
 }
 
-void *drm_intel_gem_bo_map__gtt(drm_intel_bo *bo)
+drm_public void *drm_intel_gem_bo_map__gtt(drm_intel_bo *bo)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
 	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
@@ -3505,7 +3500,7 @@ void *drm_intel_gem_bo_map__gtt(drm_inte
 	return bo_gem->gtt_virtual;
 }
 
-void *drm_intel_gem_bo_map__cpu(drm_intel_bo *bo)
+drm_public void *drm_intel_gem_bo_map__cpu(drm_intel_bo *bo)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
 	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
@@ -3549,7 +3544,7 @@ void *drm_intel_gem_bo_map__cpu(drm_inte
 	return bo_gem->mem_virtual;
 }
 
-void *drm_intel_gem_bo_map__wc(drm_intel_bo *bo)
+drm_public void *drm_intel_gem_bo_map__wc(drm_intel_bo *bo)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
 	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
@@ -3598,7 +3593,7 @@ void *drm_intel_gem_bo_map__wc(drm_intel
  *
  * \param fd File descriptor of the opened DRM device.
  */
-drm_intel_bufmgr *
+drm_public drm_intel_bufmgr *
 drm_intel_bufmgr_gem_init(int fd, int batch_size)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem;
@@ -3659,11 +3654,7 @@ drm_intel_bufmgr_gem_init(int fd, int ba
 		bufmgr_gem->gen = 7;
 	else if (IS_GEN8(bufmgr_gem->pci_device))
 		bufmgr_gem->gen = 8;
-	else if (IS_GEN9(bufmgr_gem->pci_device))
-		bufmgr_gem->gen = 9;
-	else if (IS_GEN10(bufmgr_gem->pci_device))
-		bufmgr_gem->gen = 10;
-	else {
+	else if (!intel_get_genx(bufmgr_gem->pci_device, &bufmgr_gem->gen)) {
 		free(bufmgr_gem);
 		bufmgr_gem = NULL;
 		goto exit;

Index: xsrc/external/mit/libdrm/dist/radeon/radeon_bo_gem.c
diff -u xsrc/external/mit/libdrm/dist/radeon/radeon_bo_gem.c:1.7 xsrc/external/mit/libdrm/dist/radeon/radeon_bo_gem.c:1.8
--- xsrc/external/mit/libdrm/dist/radeon/radeon_bo_gem.c:1.7	Wed Aug 17 02:16:17 2016
+++ xsrc/external/mit/libdrm/dist/radeon/radeon_bo_gem.c	Thu Jan 10 08:59:43 2019
@@ -29,9 +29,6 @@
  *      Dave Airlie
  *      Jérôme Glisse <[email protected]>
  */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -285,7 +282,7 @@ static const struct radeon_bo_funcs bo_g
     .bo_is_referenced_by_cs = NULL,
 };
 
-struct radeon_bo_manager *radeon_bo_manager_gem_ctor(int fd)
+drm_public struct radeon_bo_manager *radeon_bo_manager_gem_ctor(int fd)
 {
     struct bo_manager_gem *bomg;
 
@@ -298,7 +295,7 @@ struct radeon_bo_manager *radeon_bo_mana
     return (struct radeon_bo_manager*)bomg;
 }
 
-void radeon_bo_manager_gem_dtor(struct radeon_bo_manager *bom)
+drm_public void radeon_bo_manager_gem_dtor(struct radeon_bo_manager *bom)
 {
     struct bo_manager_gem *bomg = (struct bo_manager_gem*)bom;
 
@@ -308,21 +305,21 @@ void radeon_bo_manager_gem_dtor(struct r
     free(bomg);
 }
 
-uint32_t
+drm_public uint32_t
 radeon_gem_name_bo(struct radeon_bo *bo)
 {
     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
     return bo_gem->name;
 }
 
-void *
+drm_public void *
 radeon_gem_get_reloc_in_cs(struct radeon_bo *bo)
 {
     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
     return &bo_gem->reloc_in_cs;
 }
 
-int
+drm_public int
 radeon_gem_get_kernel_name(struct radeon_bo *bo, uint32_t *name)
 {
     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
@@ -344,7 +341,7 @@ radeon_gem_get_kernel_name(struct radeon
     return 0;
 }
 
-int
+drm_public int
 radeon_gem_set_domain(struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain)
 {
     struct radeon_bo_int *boi = (struct radeon_bo_int *)bo;
@@ -362,7 +359,7 @@ radeon_gem_set_domain(struct radeon_bo *
     return r;
 }
 
-int radeon_gem_prime_share_bo(struct radeon_bo *bo, int *handle)
+drm_public int radeon_gem_prime_share_bo(struct radeon_bo *bo, int *handle)
 {
     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
     int ret;
@@ -371,7 +368,7 @@ int radeon_gem_prime_share_bo(struct rad
     return ret;
 }
 
-struct radeon_bo *
+drm_public struct radeon_bo *
 radeon_gem_bo_open_prime(struct radeon_bo_manager *bom, int fd_handle, uint32_t size)
 {
     struct radeon_bo_gem *bo;
Index: xsrc/external/mit/libdrm/dist/radeon/radeon_cs_gem.c
diff -u xsrc/external/mit/libdrm/dist/radeon/radeon_cs_gem.c:1.7 xsrc/external/mit/libdrm/dist/radeon/radeon_cs_gem.c:1.8
--- xsrc/external/mit/libdrm/dist/radeon/radeon_cs_gem.c:1.7	Sat Mar  4 23:22:48 2017
+++ xsrc/external/mit/libdrm/dist/radeon/radeon_cs_gem.c	Thu Jan 10 08:59:43 2019
@@ -29,9 +29,6 @@
  *      Nicolai Haehnle <[email protected]>
  *      Jérôme Glisse <[email protected]>
  */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
 #include <assert.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -540,7 +537,7 @@ static int radeon_get_device_id(int fd, 
     return r;
 }
 
-struct radeon_cs_manager *radeon_cs_manager_gem_ctor(int fd)
+drm_public struct radeon_cs_manager *radeon_cs_manager_gem_ctor(int fd)
 {
     struct radeon_cs_manager_gem *csm;
 
@@ -554,7 +551,7 @@ struct radeon_cs_manager *radeon_cs_mana
     return &csm->base;
 }
 
-void radeon_cs_manager_gem_dtor(struct radeon_cs_manager *csm)
+drm_public void radeon_cs_manager_gem_dtor(struct radeon_cs_manager *csm)
 {
     free(csm);
 }

Index: xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c
diff -u xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c:1.10 xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c:1.11
--- xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c:1.10	Tue Aug 29 06:31:24 2017
+++ xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c	Thu Jan 10 08:59:43 2019
@@ -26,9 +26,6 @@
  * Authors:
  *      Jérôme Glisse <[email protected]>
  */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
 #include <stdbool.h>
 #include <assert.h>
 #include <errno.h>
@@ -2411,7 +2408,7 @@ static int cik_surface_best(struct radeo
 /* ===========================================================================
  * public API
  */
-struct radeon_surface_manager *
+drm_public struct radeon_surface_manager *
 radeon_surface_manager_new(int fd)
 {
     struct radeon_surface_manager *surf_man;
@@ -2460,7 +2457,7 @@ out_err:
     return NULL;
 }
 
-void
+drm_public void
 radeon_surface_manager_free(struct radeon_surface_manager *surf_man)
 {
     free(surf_man);
@@ -2534,7 +2531,7 @@ static int radeon_surface_sanity(struct 
     return 0;
 }
 
-int
+drm_public int
 radeon_surface_init(struct radeon_surface_manager *surf_man,
                     struct radeon_surface *surf)
 {
@@ -2551,7 +2548,7 @@ radeon_surface_init(struct radeon_surfac
     return surf_man->surface_init(surf_man, surf);
 }
 
-int
+drm_public int
 radeon_surface_best(struct radeon_surface_manager *surf_man,
                     struct radeon_surface *surf)
 {

Index: xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c
diff -u xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c:1.11 xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c:1.12
--- xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c:1.11	Wed Mar 14 07:19:26 2018
+++ xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c	Thu Jan 10 08:59:43 2019
@@ -38,10 +38,6 @@
  *       the mode has been programmed, along with possible test patterns.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <assert.h>
 #include <ctype.h>
 #include <stdbool.h>
@@ -123,6 +119,9 @@ struct device {
 		struct bo *bo;
 		struct bo *cursor_bo;
 	} mode;
+
+	int use_atomic;
+	drmModeAtomicReq *req;
 };
 
 static inline int64_t U642I64(uint64_t val)
@@ -620,8 +619,6 @@ static struct resources *get_resources(s
 
 	drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
 
-	drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
-
 	res->res = drmModeGetResources(dev->fd);
 	if (!res->res) {
 		fprintf(stderr, "drmModeGetResources failed: %s\n",
@@ -811,7 +808,9 @@ struct plane_arg {
 	uint32_t w, h;
 	double scale;
 	unsigned int fb_id;
+	unsigned int old_fb_id;
 	struct bo *bo;
+	struct bo *old_bo;
 	char format_str[5]; /* need to leave room for terminating \0 */
 	unsigned int fourcc;
 };
@@ -1005,8 +1004,12 @@ static void set_property(struct device *
 
 	p->prop_id = props->props[i];
 
-	ret = drmModeObjectSetProperty(dev->fd, p->obj_id, p->obj_type,
-				       p->prop_id, p->value);
+	if (!dev->use_atomic)
+		ret = drmModeObjectSetProperty(dev->fd, p->obj_id, p->obj_type,
+									   p->prop_id, p->value);
+	else
+		ret = drmModeAtomicAddProperty(dev->req, p->obj_id, p->prop_id, p->value);
+
 	if (ret < 0)
 		fprintf(stderr, "failed to set %s %i property %s to %" PRIu64 ": %s\n",
 			obj_type, p->obj_id, p->name, p->value, strerror(errno));
@@ -1055,6 +1058,94 @@ static bool format_support(const drmMode
 	return false;
 }
 
+static void add_property(struct device *dev, uint32_t obj_id,
+			       const char *name, uint64_t value)
+{
+	struct property_arg p;
+
+	p.obj_id = obj_id;
+	strcpy(p.name, name);
+	p.value = value;
+
+	set_property(dev, &p);
+}
+
+static int atomic_set_plane(struct device *dev, struct plane_arg *p,
+							int pattern, bool update)
+{
+	uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
+	struct bo *plane_bo;
+	int crtc_x, crtc_y, crtc_w, crtc_h;
+	struct crtc *crtc = NULL;
+	unsigned int i;
+	unsigned int old_fb_id;
+
+	/* Find an unused plane which can be connected to our CRTC. Find the
+	 * CRTC index first, then iterate over available planes.
+	 */
+	for (i = 0; i < (unsigned int)dev->resources->res->count_crtcs; i++) {
+		if (p->crtc_id == dev->resources->res->crtcs[i]) {
+			crtc = &dev->resources->crtcs[i];
+			break;
+		}
+	}
+
+	if (!crtc) {
+		fprintf(stderr, "CRTC %u not found\n", p->crtc_id);
+		return -1;
+	}
+
+	if (!update)
+		fprintf(stderr, "testing %dx%d@%s on plane %u, crtc %u\n",
+			p->w, p->h, p->format_str, p->plane_id, p->crtc_id);
+
+	plane_bo = p->old_bo;
+	p->old_bo = p->bo;
+
+	if (!plane_bo) {
+		plane_bo = bo_create(dev->fd, p->fourcc, p->w, p->h,
+				     handles, pitches, offsets, pattern);
+
+		if (plane_bo == NULL)
+			return -1;
+
+		if (drmModeAddFB2(dev->fd, p->w, p->h, p->fourcc,
+			handles, pitches, offsets, &p->fb_id, 0)) {
+			fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
+			return -1;
+		}
+	}
+
+	p->bo = plane_bo;
+
+	old_fb_id = p->fb_id;
+	p->old_fb_id = old_fb_id;
+
+	crtc_w = p->w * p->scale;
+	crtc_h = p->h * p->scale;
+	if (!p->has_position) {
+		/* Default to the middle of the screen */
+		crtc_x = (crtc->mode->hdisplay - crtc_w) / 2;
+		crtc_y = (crtc->mode->vdisplay - crtc_h) / 2;
+	} else {
+		crtc_x = p->x;
+		crtc_y = p->y;
+	}
+
+	add_property(dev, p->plane_id, "FB_ID", p->fb_id);
+	add_property(dev, p->plane_id, "CRTC_ID", p->crtc_id);
+	add_property(dev, p->plane_id, "SRC_X", 0);
+	add_property(dev, p->plane_id, "SRC_Y", 0);
+	add_property(dev, p->plane_id, "SRC_W", p->w << 16);
+	add_property(dev, p->plane_id, "SRC_H", p->h << 16);
+	add_property(dev, p->plane_id, "CRTC_X", crtc_x);
+	add_property(dev, p->plane_id, "CRTC_Y", crtc_y);
+	add_property(dev, p->plane_id, "CRTC_W", crtc_w);
+	add_property(dev, p->plane_id, "CRTC_H", crtc_h);
+
+	return 0;
+}
+
 static int set_plane(struct device *dev, struct plane_arg *p)
 {
 	drmModePlane *ovr;
@@ -1151,6 +1242,64 @@ static int set_plane(struct device *dev,
 	return 0;
 }
 
+static void atomic_set_planes(struct device *dev, struct plane_arg *p,
+			      unsigned int count, bool update)
+{
+	unsigned int i, pattern = UTIL_PATTERN_SMPTE;
+
+	/* set up planes */
+	for (i = 0; i < count; i++) {
+		if (i > 0)
+			pattern = UTIL_PATTERN_TILES;
+
+		if (atomic_set_plane(dev, &p[i], pattern, update))
+			return;
+	}
+}
+
+static void atomic_clear_planes(struct device *dev, struct plane_arg *p, unsigned int count)
+{
+	unsigned int i;
+
+	for (i = 0; i < count; i++) {
+		add_property(dev, p[i].plane_id, "FB_ID", 0);
+		add_property(dev, p[i].plane_id, "CRTC_ID", 0);
+		add_property(dev, p[i].plane_id, "SRC_X", 0);
+		add_property(dev, p[i].plane_id, "SRC_Y", 0);
+		add_property(dev, p[i].plane_id, "SRC_W", 0);
+		add_property(dev, p[i].plane_id, "SRC_H", 0);
+		add_property(dev, p[i].plane_id, "CRTC_X", 0);
+		add_property(dev, p[i].plane_id, "CRTC_Y", 0);
+		add_property(dev, p[i].plane_id, "CRTC_W", 0);
+		add_property(dev, p[i].plane_id, "CRTC_H", 0);
+	}
+}
+
+static void atomic_clear_FB(struct device *dev, struct plane_arg *p, unsigned int count)
+{
+	unsigned int i;
+
+	for (i = 0; i < count; i++) {
+		if (p[i].fb_id) {
+			drmModeRmFB(dev->fd, p[i].fb_id);
+			p[i].fb_id = 0;
+		}
+		if (p[i].old_fb_id) {
+			drmModeRmFB(dev->fd, p[i].old_fb_id);
+			p[i].old_fb_id = 0;
+		}
+		if (p[i].bo) {
+			bo_destroy(p[i].bo);
+			p[i].bo = NULL;
+		}
+		if (p[i].old_bo) {
+			bo_destroy(p[i].old_bo);
+			p[i].old_bo = NULL;
+		}
+
+	}
+}
+
 static void clear_planes(struct device *dev, struct plane_arg *p, unsigned int count)
 {
 	unsigned int i;
@@ -1163,6 +1312,59 @@ static void clear_planes(struct device *
 	}
 }
 
+static void atomic_set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
+{
+	unsigned int i;
+	unsigned int j;
+	int ret;
+
+	for (i = 0; i < count; i++) {
+		struct pipe_arg *pipe = &pipes[i];
+
+		ret = pipe_find_crtc_and_mode(dev, pipe);
+		if (ret < 0)
+			continue;
+	}
+
+	for (i = 0; i < count; i++) {
+		struct pipe_arg *pipe = &pipes[i];
+		uint32_t blob_id;
+
+		if (pipe->mode == NULL)
+			continue;
+
+		printf("setting mode %s-%dHz@%s on connectors ",
+		       pipe->mode_str, pipe->mode->vrefresh, pipe->format_str);
+		for (j = 0; j < pipe->num_cons; ++j) {
+			printf("%s, ", pipe->cons[j]);
+			add_property(dev, pipe->con_ids[j], "CRTC_ID", pipe->crtc->crtc->crtc_id);
+		}
+		printf("crtc %d\n", pipe->crtc->crtc->crtc_id);
+
+		drmModeCreatePropertyBlob(dev->fd, pipe->mode, sizeof(*pipe->mode), &blob_id);
+		add_property(dev, pipe->crtc->crtc->crtc_id, "MODE_ID", blob_id);
+		add_property(dev, pipe->crtc->crtc->crtc_id, "ACTIVE", 1);
+	}
+}
+
+static void atomic_clear_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
+{
+	unsigned int i;
+	unsigned int j;
+
+	for (i = 0; i < count; i++) {
+		struct pipe_arg *pipe = &pipes[i];
+
+		if (pipe->mode == NULL)
+			continue;
+
+		for (j = 0; j < pipe->num_cons; ++j)
+			add_property(dev, pipe->con_ids[j], "CRTC_ID",0);
+
+		add_property(dev, pipe->crtc->crtc->crtc_id, "MODE_ID", 0);
+		add_property(dev, pipe->crtc->crtc->crtc_id, "ACTIVE", 0);
+	}
+}
 
 static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
 {
@@ -1538,7 +1740,7 @@ static int parse_property(struct propert
 
 static void usage(char *name)
 {
-	fprintf(stderr, "usage: %s [-cDdefMPpsCvw]\n", name);
+	fprintf(stderr, "usage: %s [-acDdefMPpsCvw]\n", name);
 
 	fprintf(stderr, "\n Query options:\n\n");
 	fprintf(stderr, "\t-c\tlist connectors\n");
@@ -1552,6 +1754,7 @@ static void usage(char *name)
 	fprintf(stderr, "\t-C\ttest hw cursor\n");
 	fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
 	fprintf(stderr, "\t-w <obj_id>:<prop_name>:<value>\tset property\n");
+	fprintf(stderr, "\t-a \tuse atomic API\n");
 
 	fprintf(stderr, "\n Generic options:\n\n");
 	fprintf(stderr, "\t-d\tdrop master after mode set\n");
@@ -1615,7 +1818,7 @@ static int pipe_resolve_connectors(struc
 	return 0;
 }
 
-static char optstr[] = "cdD:efM:P:ps:Cvw:";
+static char optstr[] = "acdD:efM:P:ps:Cvw:";
 
 int main(int argc, char **argv)
 {
@@ -1626,6 +1829,7 @@ int main(int argc, char **argv)
 	int drop_master = 0;
 	int test_vsync = 0;
 	int test_cursor = 0;
+	int use_atomic = 0;
 	char *device = NULL;
 	char *module = NULL;
 	unsigned int i;
@@ -1644,6 +1848,9 @@ int main(int argc, char **argv)
 		args++;
 
 		switch (c) {
+		case 'a':
+			use_atomic = 1;
+			break;
 		case 'c':
 			connectors = 1;
 			break;
@@ -1723,13 +1930,22 @@ int main(int argc, char **argv)
 		}
 	}
 
-	if (!args)
+	if (!args || (args == 1 && use_atomic))
 		encoders = connectors = crtcs = planes = framebuffers = 1;
 
 	dev.fd = util_open(device, module);
 	if (dev.fd < 0)
 		return -1;
 
+	ret = drmSetClientCap(dev.fd, DRM_CLIENT_CAP_ATOMIC, 1);
+	if (ret && use_atomic) {
+		fprintf(stderr, "no atomic modesetting support: %s\n", strerror(errno));
+		drmClose(dev.fd);
+		return -1;
+	}
+
+	dev.use_atomic = use_atomic;
+
 	if (test_vsync && !page_flipping_supported()) {
 		fprintf(stderr, "page flipping not supported by drm.\n");
 		return -1;
@@ -1770,36 +1986,111 @@ int main(int argc, char **argv)
 	for (i = 0; i < prop_count; ++i)
 		set_property(&dev, &prop_args[i]);
 
-	if (count || plane_count) {
-		uint64_t cap = 0;
+	if (dev.use_atomic) {
+		dev.req = drmModeAtomicAlloc();
 
-		ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);
-		if (ret || cap == 0) {
-			fprintf(stderr, "driver doesn't support the dumb buffer API\n");
-			return 1;
+		if (count && plane_count) {
+			uint64_t cap = 0;
+
+			ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);
+			if (ret || cap == 0) {
+				fprintf(stderr, "driver doesn't support the dumb buffer API\n");
+				return 1;
+			}
+
+			atomic_set_mode(&dev, pipe_args, count);
+			atomic_set_planes(&dev, plane_args, plane_count, false);
+
+			ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+			if (ret) {
+				fprintf(stderr, "Atomic Commit failed [1]\n");
+				return 1;
+			}
+
+			gettimeofday(&pipe_args->start, NULL);
+			pipe_args->swap_count = 0;
+
+			while (test_vsync) {
+				drmModeAtomicFree(dev.req);
+				dev.req = drmModeAtomicAlloc();
+				atomic_set_planes(&dev, plane_args, plane_count, true);
+
+				ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+				if (ret) {
+					fprintf(stderr, "Atomic Commit failed [2]\n");
+					return 1;
+				}
+
+				pipe_args->swap_count++;
+				if (pipe_args->swap_count == 60) {
+					struct timeval end;
+					double t;
+
+					gettimeofday(&end, NULL);
+					t = end.tv_sec + end.tv_usec * 1e-6 -
+				    (pipe_args->start.tv_sec + pipe_args->start.tv_usec * 1e-6);
+					fprintf(stderr, "freq: %.02fHz\n", pipe_args->swap_count / t);
+					pipe_args->swap_count = 0;
+					pipe_args->start = end;
+				}
+			}
+
+			if (drop_master)
+				drmDropMaster(dev.fd);
+
+			getchar();
+
+			drmModeAtomicFree(dev.req);
+			dev.req = drmModeAtomicAlloc();
+
+			atomic_clear_mode(&dev, pipe_args, count);
+			atomic_clear_planes(&dev, plane_args, plane_count);
+			ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+			if (ret) {
+				fprintf(stderr, "Atomic Commit failed\n");
+				return 1;
+			}
+
+			atomic_clear_FB(&dev, plane_args, plane_count);
 		}
 
-		if (count)
-			set_mode(&dev, pipe_args, count);
+		drmModeAtomicFree(dev.req);
+	} else {
+		if (count || plane_count) {
+			uint64_t cap = 0;
 
-		if (plane_count)
-			set_planes(&dev, plane_args, plane_count);
+			ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);
+			if (ret || cap == 0) {
+				fprintf(stderr, "driver doesn't support the dumb buffer API\n");
+				return 1;
+			}
 
-		if (test_cursor)
-			set_cursors(&dev, pipe_args, count);
+			if (count)
+				set_mode(&dev, pipe_args, count);
 
-		if (test_vsync)
-			test_page_flip(&dev, pipe_args, count);
+			if (plane_count)
+				set_planes(&dev, plane_args, plane_count);
 
-		if (drop_master)
-			drmDropMaster(dev.fd);
+			if (test_cursor)
+				set_cursors(&dev, pipe_args, count);
 
-		getchar();
+			if (test_vsync)
+				test_page_flip(&dev, pipe_args, count);
 
-		if (test_cursor)
-			clear_cursors(&dev);
+			if (drop_master)
+				drmDropMaster(dev.fd);
 
-		bo_destroy(dev.mode.bo);
+			getchar();
+
+			if (test_cursor)
+				clear_cursors(&dev);
+
+			if (plane_count)
+				clear_planes(&dev, plane_args, plane_count);
+
+			if (count)
+				clear_mode(&dev);
+		}
 	}
 
 	free_resources(dev.resources);

Reply via email to