Module Name: xsrc Committed By: mrg Date: Thu Jul 4 09:22:57 UTC 2024
Modified Files: xsrc/external/mit/libdrm/dist: configure libsync.h xf86drm.c xf86drm.h xf86drmMode.c xf86drmMode.h xsrc/external/mit/libdrm/dist/amdgpu: amdgpu.h amdgpu_bo.c amdgpu_vamgr.c xsrc/external/mit/libdrm/dist/include/drm: drm.h xsrc/external/mit/libdrm/dist/intel: intel_bufmgr_gem.c uthash.h xsrc/external/mit/libdrm/dist/radeon: radeon_surface.c xsrc/external/mit/libdrm/dist/tests/modetest: modetest.c Removed Files: xsrc/external/mit/libdrm/dist/intel: i915_pciids.h intel_chipset.c Log Message: merge libdrm 2.4.122 To generate a diff of this commit: cvs rdiff -u -r1.5 -r1.6 xsrc/external/mit/libdrm/dist/configure cvs rdiff -u -r1.3 -r1.4 xsrc/external/mit/libdrm/dist/libsync.h cvs rdiff -u -r1.32 -r1.33 xsrc/external/mit/libdrm/dist/xf86drm.c cvs rdiff -u -r1.16 -r1.17 xsrc/external/mit/libdrm/dist/xf86drm.h cvs rdiff -u -r1.21 -r1.22 xsrc/external/mit/libdrm/dist/xf86drmMode.c cvs rdiff -u -r1.14 -r1.15 xsrc/external/mit/libdrm/dist/xf86drmMode.h cvs rdiff -u -r1.4 -r1.5 xsrc/external/mit/libdrm/dist/amdgpu/amdgpu.h \ xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_vamgr.c cvs rdiff -u -r1.6 -r1.7 xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_bo.c cvs rdiff -u -r1.14 -r1.15 xsrc/external/mit/libdrm/dist/include/drm/drm.h cvs rdiff -u -r1.1.1.9 -r0 xsrc/external/mit/libdrm/dist/intel/i915_pciids.h cvs rdiff -u -r1.22 -r1.23 \ xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c cvs rdiff -u -r1.1.1.6 -r0 \ xsrc/external/mit/libdrm/dist/intel/intel_chipset.c cvs rdiff -u -r1.2 -r1.3 xsrc/external/mit/libdrm/dist/intel/uthash.h cvs rdiff -u -r1.11 -r1.12 \ xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c cvs rdiff -u -r1.19 -r1.20 \ 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/configure diff -u xsrc/external/mit/libdrm/dist/configure:1.5 xsrc/external/mit/libdrm/dist/configure:1.6 --- xsrc/external/mit/libdrm/dist/configure:1.5 Fri Nov 3 17:05:41 2023 +++ xsrc/external/mit/libdrm/dist/configure Thu Jul 4 09:22:57 2024 @@ -3,6 +3,6 @@ # Identity of this package. PACKAGE_NAME='libdrm' PACKAGE_TARNAME='libdrm' -PACKAGE_VERSION='2.4.114' -PACKAGE_STRING='libdrm 2.4.114' +PACKAGE_VERSION='2.4.122' +PACKAGE_STRING='libdrm 2.4.122' PACKAGE_URL='' Index: xsrc/external/mit/libdrm/dist/libsync.h diff -u xsrc/external/mit/libdrm/dist/libsync.h:1.3 xsrc/external/mit/libdrm/dist/libsync.h:1.4 --- xsrc/external/mit/libdrm/dist/libsync.h:1.3 Tue Mar 7 16:28:42 2017 +++ xsrc/external/mit/libdrm/dist/libsync.h Thu Jul 4 09:22:57 2024 @@ -33,7 +33,7 @@ #include <stdint.h> #include <string.h> #include <sys/ioctl.h> -#include <sys/poll.h> +#include <poll.h> #include <unistd.h> #if defined(__cplusplus) Index: xsrc/external/mit/libdrm/dist/xf86drm.c diff -u xsrc/external/mit/libdrm/dist/xf86drm.c:1.32 xsrc/external/mit/libdrm/dist/xf86drm.c:1.33 --- xsrc/external/mit/libdrm/dist/xf86drm.c:1.32 Sat Nov 12 02:07:07 2022 +++ xsrc/external/mit/libdrm/dist/xf86drm.c Thu Jul 4 09:22:57 2024 @@ -60,7 +60,6 @@ #if HAVE_SYS_SYSCTL_H #include <sys/sysctl.h> #endif -#include <math.h> #include <inttypes.h> #if defined(__FreeBSD__) @@ -179,11 +178,15 @@ drmGetFormatModifierNameFromAmd(uint64_t static char * drmGetFormatModifierNameFromAmlogic(uint64_t modifier); +static char * +drmGetFormatModifierNameFromVivante(uint64_t modifier); + static const struct drmVendorInfo modifier_format_vendor_table[] = { { DRM_FORMAT_MOD_VENDOR_ARM, drmGetFormatModifierNameFromArm }, { DRM_FORMAT_MOD_VENDOR_NVIDIA, drmGetFormatModifierNameFromNvidia }, { DRM_FORMAT_MOD_VENDOR_AMD, drmGetFormatModifierNameFromAmd }, { DRM_FORMAT_MOD_VENDOR_AMLOGIC, drmGetFormatModifierNameFromAmlogic }, + { DRM_FORMAT_MOD_VENDOR_VIVANTE, drmGetFormatModifierNameFromVivante }, }; #ifndef AFBC_FORMAT_MOD_MODE_VALUE_MASK @@ -478,6 +481,9 @@ drmGetFormatModifierNameFromAmd(uint64_t case AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS: str_tile_version = "GFX10_RBPLUS"; break; + case AMD_FMT_MOD_TILE_VER_GFX11: + str_tile_version = "GFX11"; + break; } if (str_tile_version) { @@ -505,6 +511,9 @@ drmGetFormatModifierNameFromAmd(uint64_t case AMD_FMT_MOD_TILE_GFX9_64K_R_X: str_tile = "GFX9_64K_R_X"; break; + case AMD_FMT_MOD_TILE_GFX11_256K_R_X: + str_tile = "GFX11_256K_R_X"; + break; } if (str_tile) @@ -551,6 +560,70 @@ drmGetFormatModifierNameFromAmlogic(uint return mod_amlogic; } +static char * +drmGetFormatModifierNameFromVivante(uint64_t modifier) +{ + const char *color_tiling, *tile_status, *compression; + char *mod_vivante = NULL; + + switch (modifier & VIVANTE_MOD_TS_MASK) { + case 0: + tile_status = ""; + break; + case VIVANTE_MOD_TS_64_4: + tile_status = ",TS=64B_4"; + break; + case VIVANTE_MOD_TS_64_2: + tile_status = ",TS=64B_2"; + break; + case VIVANTE_MOD_TS_128_4: + tile_status = ",TS=128B_4"; + break; + case VIVANTE_MOD_TS_256_4: + tile_status = ",TS=256B_4"; + break; + default: + tile_status = ",TS=UNKNOWN"; + break; + } + + switch (modifier & VIVANTE_MOD_COMP_MASK) { + case 0: + compression = ""; + break; + case VIVANTE_MOD_COMP_DEC400: + compression = ",COMP=DEC400"; + break; + default: + compression = ",COMP=UNKNOWN"; + break; + } + + switch (modifier & ~VIVANTE_MOD_EXT_MASK) { + case 0: + color_tiling = "LINEAR"; + break; + case DRM_FORMAT_MOD_VIVANTE_TILED: + color_tiling = "TILED"; + break; + case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED: + color_tiling = "SUPER_TILED"; + break; + case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED: + color_tiling = "SPLIT_TILED"; + break; + case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED: + color_tiling = "SPLIT_SUPER_TILED"; + break; + default: + color_tiling = "UNKNOWN"; + break; + } + + asprintf(&mod_vivante, "%s%s%s", color_tiling, tile_status, compression); + return mod_vivante; +} + static unsigned log2_int(unsigned x) { unsigned l; @@ -759,8 +832,6 @@ static const char *drmGetDeviceName(int switch (type) { case DRM_NODE_PRIMARY: return DRM_DEV_NAME; - case DRM_NODE_CONTROL: - return DRM_CONTROL_DEV_NAME; case DRM_NODE_RENDER: return DRM_RENDER_DEV_NAME; } @@ -956,8 +1027,6 @@ static int drmGetMinorBase(int type) switch (type) { case DRM_NODE_PRIMARY: return 0; - case DRM_NODE_CONTROL: - return 64; case DRM_NODE_RENDER: return 128; default: @@ -978,8 +1047,6 @@ static int drmGetMinorType(int major, in // If not in /dev/drm/ we have the type in the name if (sscanf(name, "dri/card%d\n", &id) >= 1) return DRM_NODE_PRIMARY; - else if (sscanf(name, "dri/control%d\n", &id) >= 1) - return DRM_NODE_CONTROL; else if (sscanf(name, "dri/renderD%d\n", &id) >= 1) return DRM_NODE_RENDER; return -1; @@ -987,19 +1054,20 @@ static int drmGetMinorType(int major, in minor = id; #endif - int type = minor >> 6; - - if (minor < 0) - return -1; + char path[DRM_NODE_NAME_MAX]; + const char *dev_name; + int i; - switch (type) { - case DRM_NODE_PRIMARY: - case DRM_NODE_CONTROL: - case DRM_NODE_RENDER: - return type; - default: - return -1; + for (i = DRM_NODE_PRIMARY; i < DRM_NODE_MAX; i++) { + dev_name = drmGetDeviceName(i); + if (!dev_name) + continue; + snprintf(path, sizeof(path), dev_name, DRM_DIR_NAME, minor); + if (!access(path, F_OK)) + return i; } + + return -1; } static const char *drmGetMinorName(int type) @@ -1007,8 +1075,6 @@ static const char *drmGetMinorName(int t switch (type) { case DRM_NODE_PRIMARY: return DRM_PRIMARY_MINOR_NAME; - case DRM_NODE_CONTROL: - return DRM_CONTROL_MINOR_NAME; case DRM_NODE_RENDER: return DRM_RENDER_MINOR_NAME; default: @@ -1195,7 +1261,7 @@ drm_public int drmOpen(const char *name, * * \param name driver name. Not referenced if bus ID is supplied. * \param busid bus ID. Zero if not known. - * \param type the device node type to open, PRIMARY, CONTROL or RENDER + * \param type the device node type to open, PRIMARY or RENDER * * \return a file descriptor on success, or a negative value on error. * @@ -1228,7 +1294,7 @@ drm_public int drmOpenWithType(const cha drm_public int drmOpenControl(int minor) { - return drmOpenMinor(minor, 0, DRM_NODE_CONTROL); + return -EINVAL; } drm_public int drmOpenRender(int minor) @@ -3692,12 +3758,9 @@ static int get_sysctl_pci_bus_info(int m switch (type) { case DRM_NODE_PRIMARY: break; - case DRM_NODE_CONTROL: - id -= 64; - break; case DRM_NODE_RENDER: id -= 128; - break; + break; } if (id < 0) return -EINVAL; @@ -3876,10 +3939,6 @@ drm_public int drmDevicesEqual(drmDevice static int drmGetNodeType(const char *name) { - if (strncmp(name, DRM_CONTROL_MINOR_NAME, - sizeof(DRM_CONTROL_MINOR_NAME ) - 1) == 0) - return DRM_NODE_CONTROL; - if (strncmp(name, DRM_RENDER_MINOR_NAME, sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0) return DRM_NODE_RENDER; @@ -4582,14 +4641,24 @@ process_device(drmDevicePtr *device, con { struct stat sbuf; char node[PATH_MAX + 1]; - int node_type, subsystem_type; + int node_type, subsystem_type, written; unsigned int maj, min; + const int max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *)); node_type = drmGetNodeType(d_name); if (node_type < 0) return -1; - snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, d_name); + written = snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, d_name); + if (written < 0) + return -1; + + /* anything longer than this will be truncated in drmDeviceAlloc. + * Account for NULL byte + */ + if (written + 1 > max_node_length) + return -1; + if (stat(node, &sbuf)) return -1; @@ -4696,6 +4765,8 @@ drm_public int drmGetDeviceFromDevId(dev const char *dev_name; int node_type, subsystem_type; int maj, min, n, ret; + const int max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *)); + struct stat sbuf; if (device == NULL) return -EINVAL; @@ -4714,9 +4785,14 @@ drm_public int drmGetDeviceFromDevId(dev if (!dev_name) return -EINVAL; + /* anything longer than this will be truncated in drmDeviceAlloc. + * Account for NULL byte + */ n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min); if (n == -1 || n >= PATH_MAX) return -errno; + if (n + 1 > max_node_length) + return -EINVAL; if (stat(node, &sbuf)) return -EINVAL; @@ -4798,6 +4874,23 @@ drm_public int drmGetDeviceFromDevId(dev #endif } +drm_public int drmGetNodeTypeFromDevId(dev_t devid) +{ + int maj, min, node_type; + + maj = major(devid); + min = minor(devid); + + if (!drmNodeIsDRM(maj, min)) + return -EINVAL; + + node_type = drmGetMinorType(maj, min); + if (node_type == -1) + return -ENODEV; + + return node_type; +} + /** * Get information about the opened drm device * @@ -5215,6 +5308,20 @@ drm_public int drmSyncobjTransfer(int fd return ret; } +drm_public int drmSyncobjEventfd(int fd, uint32_t handle, uint64_t point, int ev_fd, + uint32_t flags) +{ + struct drm_syncobj_eventfd args; + + memclear(args); + args.handle = handle; + args.point = point; + args.fd = ev_fd; + args.flags = flags; + + return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_EVENTFD, &args); +} + static char * drmGetFormatModifierFromSimpleTokens(uint64_t modifier) { Index: xsrc/external/mit/libdrm/dist/xf86drm.h diff -u xsrc/external/mit/libdrm/dist/xf86drm.h:1.16 xsrc/external/mit/libdrm/dist/xf86drm.h:1.17 --- xsrc/external/mit/libdrm/dist/xf86drm.h:1.16 Sat Nov 12 02:07:07 2022 +++ xsrc/external/mit/libdrm/dist/xf86drm.h Thu Jul 4 09:22:57 2024 @@ -48,7 +48,7 @@ extern "C" { #endif #ifndef DRM_MAX_MINOR -#define DRM_MAX_MINOR 16 +#define DRM_MAX_MINOR 64 /* deprecated */ #endif #if defined(__linux__) @@ -83,18 +83,18 @@ extern "C" { #ifdef __OpenBSD__ #define DRM_DIR_NAME "/dev" #define DRM_PRIMARY_MINOR_NAME "drm" -#define DRM_CONTROL_MINOR_NAME "drmC" +#define DRM_CONTROL_MINOR_NAME "drmC" /* deprecated */ #define DRM_RENDER_MINOR_NAME "drmR" #else #define DRM_DIR_NAME "/dev/dri" #define DRM_PRIMARY_MINOR_NAME "card" -#define DRM_CONTROL_MINOR_NAME "controlD" +#define DRM_CONTROL_MINOR_NAME "controlD" /* deprecated */ #define DRM_RENDER_MINOR_NAME "renderD" #define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */ #endif #define DRM_DEV_NAME "%s/" DRM_PRIMARY_MINOR_NAME "%d" -#define DRM_CONTROL_DEV_NAME "%s/" DRM_CONTROL_MINOR_NAME "%d" +#define DRM_CONTROL_DEV_NAME "%s/" DRM_CONTROL_MINOR_NAME "%d" /* deprecated */ #define DRM_RENDER_DEV_NAME "%s/" DRM_RENDER_MINOR_NAME "%d" #define DRM_NODE_NAME_MAX \ @@ -102,7 +102,7 @@ extern "C" { + MAX3(sizeof(DRM_PRIMARY_MINOR_NAME), \ sizeof(DRM_CONTROL_MINOR_NAME), \ sizeof(DRM_RENDER_MINOR_NAME)) \ - + sizeof("144") /* highest possible node number */ \ + + sizeof("1048575") /* highest possible node number 2^MINORBITS - 1 */ \ + 1) /* NULL-terminator */ #define DRM_ERR_NO_DEVICE (-1001) @@ -605,14 +605,14 @@ extern int drmAvailable(void); extern int drmOpen(const char *name, const char *busid); #define DRM_NODE_PRIMARY 0 -#define DRM_NODE_CONTROL 1 +#define DRM_NODE_CONTROL 1 /* deprecated: never returned */ #define DRM_NODE_RENDER 2 #define DRM_NODE_MAX 3 extern int drmOpenWithType(const char *name, const char *busid, int type); -extern int drmOpenControl(int minor); +extern int drmOpenControl(int minor); /* deprecated: always fails */ extern int drmOpenRender(int minor); extern int drmClose(int fd); extern drmVersionPtr drmGetVersion(int fd); @@ -817,7 +817,7 @@ extern int drmHandleEvent(int fd, drmEve extern char *drmGetDeviceNameFromFd(int fd); /* Improved version of drmGetDeviceNameFromFd which attributes for any type of - * device/node - card, control or renderD. + * device/node - card or renderD. */ extern char *drmGetDeviceNameFromFd2(int fd); extern int drmGetNodeTypeFromFd(int fd); @@ -928,6 +928,18 @@ extern int drmGetDevices2(uint32_t flags extern int drmGetDeviceFromDevId(dev_t dev_id, uint32_t flags, drmDevicePtr *device); +/** + * Get the node type (DRM_NODE_PRIMARY or DRM_NODE_RENDER) from a device ID. + * + * Returns negative errno on error. + */ +extern int drmGetNodeTypeFromDevId(dev_t devid); + +/** + * Check if two drmDevice pointers represent the same DRM device. + * + * Returns 1 if the devices are equal, 0 otherwise. + */ extern int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b); extern int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle); @@ -956,6 +968,8 @@ extern int drmSyncobjTransfer(int fd, uint32_t dst_handle, uint64_t dst_point, uint32_t src_handle, uint64_t src_point, uint32_t flags); +extern int drmSyncobjEventfd(int fd, uint32_t handle, uint64_t point, int ev_fd, + uint32_t flags); extern char * drmGetFormatModifierVendor(uint64_t modifier); Index: xsrc/external/mit/libdrm/dist/xf86drmMode.c diff -u xsrc/external/mit/libdrm/dist/xf86drmMode.c:1.21 xsrc/external/mit/libdrm/dist/xf86drmMode.c:1.22 --- xsrc/external/mit/libdrm/dist/xf86drmMode.c:1.21 Sat Nov 12 02:07:07 2022 +++ xsrc/external/mit/libdrm/dist/xf86drmMode.c Thu Jul 4 09:22:57 2024 @@ -320,6 +320,16 @@ drm_public int drmModeRmFB(int fd, uint3 return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId); } +drm_public int drmModeCloseFB(int fd, uint32_t buffer_id) +{ + struct drm_mode_closefb closefb; + + memclear(closefb); + closefb.fb_id = buffer_id; + + return DRM_IOCTL(fd, DRM_IOCTL_MODE_CLOSEFB, &closefb); +} + drm_public drmModeFBPtr drmModeGetFB(int fd, uint32_t buf) { struct drm_mode_fb_cmd info; @@ -1004,8 +1014,8 @@ drm_public int drmModeCrtcGetGamma(int f } drm_public int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, - uint16_t *red, uint16_t *green, - uint16_t *blue) + const uint16_t *red, const uint16_t *green, + const uint16_t *blue) { struct drm_mode_crtc_lut l; Index: xsrc/external/mit/libdrm/dist/xf86drmMode.h diff -u xsrc/external/mit/libdrm/dist/xf86drmMode.h:1.14 xsrc/external/mit/libdrm/dist/xf86drmMode.h:1.15 --- xsrc/external/mit/libdrm/dist/xf86drmMode.h:1.14 Sat Nov 12 02:07:07 2022 +++ xsrc/external/mit/libdrm/dist/xf86drmMode.h Thu Jul 4 09:22:57 2024 @@ -315,6 +315,13 @@ int drmModeAddFB2WithModifiers(int fd, u extern int drmModeRmFB(int fd, uint32_t bufferId); /** + * Close a framebuffer. + * + * Same as drmModeRmFB(), except it doesn't implicitly disable planes and CRTCs. + */ +extern int drmModeCloseFB(int fd, uint32_t buffer_id); + +/** * Mark a region of a framebuffer as dirty. */ extern int drmModeDirtyFB(int fd, uint32_t bufferId, @@ -416,7 +423,7 @@ extern int drmModeConnectorSetProperty(i extern int drmCheckModesettingSupported(const char *busid); extern int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, - uint16_t *red, uint16_t *green, uint16_t *blue); + const uint16_t *red, const uint16_t *green, const uint16_t *blue); extern int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, uint16_t *red, uint16_t *green, uint16_t *blue); extern int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, Index: xsrc/external/mit/libdrm/dist/amdgpu/amdgpu.h diff -u xsrc/external/mit/libdrm/dist/amdgpu/amdgpu.h:1.4 xsrc/external/mit/libdrm/dist/amdgpu/amdgpu.h:1.5 --- xsrc/external/mit/libdrm/dist/amdgpu/amdgpu.h:1.4 Mon Jul 11 19:26:44 2022 +++ xsrc/external/mit/libdrm/dist/amdgpu/amdgpu.h Thu Jul 4 09:22:57 2024 @@ -142,6 +142,12 @@ typedef struct amdgpu_bo_list *amdgpu_bo typedef struct amdgpu_va *amdgpu_va_handle; /** + * Define handle dealing with VA allocation. An amdgpu_device + * owns one of these, but they can also be used without a device. + */ +typedef struct amdgpu_va_manager *amdgpu_va_manager_handle; + +/** * Define handle for semaphore */ typedef struct amdgpu_semaphore *amdgpu_semaphore_handle; @@ -531,6 +537,20 @@ int amdgpu_device_initialize(int fd, amdgpu_device_handle *device_handle); /** + * Same as amdgpu_device_initialize() except when deduplicate_device + * is false *and* fd points to a device that was already initialized. + * In this case, amdgpu_device_initialize would return the same + * amdgpu_device_handle while here amdgpu_device_initialize2 would + * return a new handle. + * amdgpu_device_initialize() should be preferred in most situations; + * the only use-case where not-deduplicating devices make sense is + * when one wants to have isolated device handles in the same process. + */ +int amdgpu_device_initialize2(int fd, bool deduplicate_device, + uint32_t *major_version, + uint32_t *minor_version, + amdgpu_device_handle *device_handle); +/** * * When access to such library does not needed any more the special * function must be call giving opportunity to clean up any @@ -1286,6 +1306,22 @@ int amdgpu_query_video_caps_info(amdgpu_ unsigned size, void *value); /** + * Query information about VM faults + * + * The return sizeof(struct drm_amdgpu_info_gpuvm_fault) + * + * \param dev - \c [in] Device handle. See #amdgpu_device_initialize() + * \param size - \c [in] Size of the returned value. + * \param value - \c [out] Pointer to the return value. + * + * \return 0 on success\n + * <0 - Negative POSIX Error code + * +*/ +int amdgpu_query_gpuvm_fault_info(amdgpu_device_handle dev, unsigned size, + void *value); + +/** * Read a set of consecutive memory-mapped registers. * Not all registers are allowed to be read by userspace. * @@ -1372,6 +1408,11 @@ int amdgpu_va_range_alloc(amdgpu_device_ int amdgpu_va_range_free(amdgpu_va_handle va_range_handle); /** + * Return the starting address of the allocated virtual address range. + */ +uint64_t amdgpu_va_get_start_addr(amdgpu_va_handle va_handle); + +/** * Query virtual address range * * UMD can query GPU VM range supported by each device @@ -1393,6 +1434,37 @@ int amdgpu_va_range_query(amdgpu_device_ uint64_t *end); /** + * Allocate a amdgpu_va_manager object. + * The returned object has be initialized with the amdgpu_va_manager_init + * before use. + * On release, amdgpu_va_manager_deinit needs to be called, then the memory + * can be released using free(). + */ +amdgpu_va_manager_handle amdgpu_va_manager_alloc(void); + +void amdgpu_va_manager_init(amdgpu_va_manager_handle va_mgr, + uint64_t low_va_offset, uint64_t low_va_max, + uint64_t high_va_offset, uint64_t high_va_max, + uint32_t virtual_address_alignment); + +void amdgpu_va_manager_deinit(amdgpu_va_manager_handle va_mgr); + +/** + * Similar to #amdgpu_va_range_alloc() but allocates VA + * directly from an amdgpu_va_manager_handle instead of using + * the manager from an amdgpu_device. + */ + +int amdgpu_va_range_alloc2(amdgpu_va_manager_handle va_mgr, + enum amdgpu_gpu_va_range va_range_type, + uint64_t size, + uint64_t va_base_alignment, + uint64_t va_base_required, + uint64_t *va_base_allocated, + amdgpu_va_handle *va_range_handle, + uint64_t flags); + +/** * VA mapping/unmapping for the buffer object * * \param bo - \c [in] BO handle Index: xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_vamgr.c diff -u xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_vamgr.c:1.4 xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_vamgr.c:1.5 --- xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_vamgr.c:1.4 Sun Jul 11 00:41:13 2021 +++ xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_vamgr.c Thu Jul 4 09:22:57 2024 @@ -229,24 +229,39 @@ drm_public int amdgpu_va_range_alloc(amd amdgpu_va_handle *va_range_handle, uint64_t flags) { + return amdgpu_va_range_alloc2(&dev->va_mgr, va_range_type, size, + va_base_alignment, va_base_required, + va_base_allocated, va_range_handle, + flags); +} + +drm_public int amdgpu_va_range_alloc2(amdgpu_va_manager_handle va_mgr, + enum amdgpu_gpu_va_range va_range_type, + uint64_t size, + uint64_t va_base_alignment, + uint64_t va_base_required, + uint64_t *va_base_allocated, + amdgpu_va_handle *va_range_handle, + uint64_t flags) +{ struct amdgpu_bo_va_mgr *vamgr; bool search_from_top = !!(flags & AMDGPU_VA_RANGE_REPLAYABLE); int ret; /* Clear the flag when the high VA manager is not initialized */ - if (flags & AMDGPU_VA_RANGE_HIGH && !dev->vamgr_high_32.va_max) + if (flags & AMDGPU_VA_RANGE_HIGH && !va_mgr->vamgr_high_32.va_max) flags &= ~AMDGPU_VA_RANGE_HIGH; if (flags & AMDGPU_VA_RANGE_HIGH) { if (flags & AMDGPU_VA_RANGE_32_BIT) - vamgr = &dev->vamgr_high_32; + vamgr = &va_mgr->vamgr_high_32; else - vamgr = &dev->vamgr_high; + vamgr = &va_mgr->vamgr_high; } else { if (flags & AMDGPU_VA_RANGE_32_BIT) - vamgr = &dev->vamgr_32; + vamgr = &va_mgr->vamgr_32; else - vamgr = &dev->vamgr; + vamgr = &va_mgr->vamgr_low; } va_base_alignment = MAX2(va_base_alignment, vamgr->va_alignment); @@ -259,9 +274,9 @@ drm_public int amdgpu_va_range_alloc(amd if (!(flags & AMDGPU_VA_RANGE_32_BIT) && ret) { /* fallback to 32bit address */ if (flags & AMDGPU_VA_RANGE_HIGH) - vamgr = &dev->vamgr_high_32; + vamgr = &va_mgr->vamgr_high_32; else - vamgr = &dev->vamgr_32; + vamgr = &va_mgr->vamgr_32; ret = amdgpu_vamgr_find_va(vamgr, size, va_base_alignment, va_base_required, search_from_top, va_base_allocated); @@ -274,7 +289,6 @@ drm_public int amdgpu_va_range_alloc(amd amdgpu_vamgr_free_va(vamgr, *va_base_allocated, size); return -ENOMEM; } - va->dev = dev; va->address = *va_base_allocated; va->size = size; va->range = va_range_type; @@ -296,3 +310,50 @@ drm_public int amdgpu_va_range_free(amdg free(va_range_handle); return 0; } + +drm_public uint64_t amdgpu_va_get_start_addr(amdgpu_va_handle va_handle) +{ + return va_handle->address; +} + +drm_public amdgpu_va_manager_handle amdgpu_va_manager_alloc(void) +{ + amdgpu_va_manager_handle r = calloc(1, sizeof(struct amdgpu_va_manager)); + return r; +} + +drm_public void amdgpu_va_manager_init(struct amdgpu_va_manager *va_mgr, + uint64_t low_va_offset, uint64_t low_va_max, + uint64_t high_va_offset, uint64_t high_va_max, + uint32_t virtual_address_alignment) +{ + uint64_t start, max; + + start = low_va_offset; + max = MIN2(low_va_max, 0x100000000ULL); + amdgpu_vamgr_init(&va_mgr->vamgr_32, start, max, + virtual_address_alignment); + + start = max; + max = MAX2(low_va_max, 0x100000000ULL); + amdgpu_vamgr_init(&va_mgr->vamgr_low, start, max, + virtual_address_alignment); + + start = high_va_offset; + max = MIN2(high_va_max, (start & ~0xffffffffULL) + 0x100000000ULL); + amdgpu_vamgr_init(&va_mgr->vamgr_high_32, start, max, + virtual_address_alignment); + + start = max; + max = MAX2(high_va_max, (start & ~0xffffffffULL) + 0x100000000ULL); + amdgpu_vamgr_init(&va_mgr->vamgr_high, start, max, + virtual_address_alignment); +} + +drm_public void amdgpu_va_manager_deinit(struct amdgpu_va_manager *va_mgr) +{ + amdgpu_vamgr_deinit(&va_mgr->vamgr_32); + amdgpu_vamgr_deinit(&va_mgr->vamgr_low); + amdgpu_vamgr_deinit(&va_mgr->vamgr_high_32); + amdgpu_vamgr_deinit(&va_mgr->vamgr_high); +} Index: xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_bo.c diff -u xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_bo.c:1.6 xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_bo.c:1.7 --- xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_bo.c:1.6 Sat Nov 12 02:07:07 2022 +++ xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_bo.c Thu Jul 4 09:22:57 2024 @@ -551,7 +551,7 @@ drm_public int amdgpu_find_bo_by_cpu_map if (!bo || !bo->cpu_ptr || size > bo->alloc_size) continue; if (cpu >= bo->cpu_ptr && - cpu < (void*)((char *)bo->cpu_ptr + bo->alloc_size)) + cpu < (void*)((uintptr_t)bo->cpu_ptr + (size_t)bo->alloc_size)) break; } Index: xsrc/external/mit/libdrm/dist/include/drm/drm.h diff -u xsrc/external/mit/libdrm/dist/include/drm/drm.h:1.14 xsrc/external/mit/libdrm/dist/include/drm/drm.h:1.15 --- xsrc/external/mit/libdrm/dist/include/drm/drm.h:1.14 Sun Jan 9 09:05:35 2022 +++ xsrc/external/mit/libdrm/dist/include/drm/drm.h Thu Jul 4 09:22:57 2024 @@ -632,8 +632,8 @@ struct drm_gem_open { /** * DRM_CAP_VBLANK_HIGH_CRTC * - * If set to 1, the kernel supports specifying a CRTC index in the high bits of - * &drm_wait_vblank_request.type. + * If set to 1, the kernel supports specifying a :ref:`CRTC index<crtc_index>` + * in the high bits of &drm_wait_vblank_request.type. * * Starting kernel version 2.6.39, this capability is always set to 1. */ @@ -670,8 +670,11 @@ struct drm_gem_open { * Bitfield of supported PRIME sharing capabilities. See &DRM_PRIME_CAP_IMPORT * and &DRM_PRIME_CAP_EXPORT. * - * PRIME buffers are exposed as dma-buf file descriptors. See - * Documentation/gpu/drm-mm.rst, section "PRIME Buffer Sharing". + * Starting from kernel version 6.6, both &DRM_PRIME_CAP_IMPORT and + * &DRM_PRIME_CAP_EXPORT are always advertised. + * + * PRIME buffers are exposed as dma-buf file descriptors. + * See :ref:`prime_buffer_sharing`. */ #define DRM_CAP_PRIME 0x5 /** @@ -679,6 +682,8 @@ struct drm_gem_open { * * If this bit is set in &DRM_CAP_PRIME, the driver supports importing PRIME * buffers via the &DRM_IOCTL_PRIME_FD_TO_HANDLE ioctl. + * + * Starting from kernel version 6.6, this bit is always set in &DRM_CAP_PRIME. */ #define DRM_PRIME_CAP_IMPORT 0x1 /** @@ -686,6 +691,8 @@ struct drm_gem_open { * * If this bit is set in &DRM_CAP_PRIME, the driver supports exporting PRIME * buffers via the &DRM_IOCTL_PRIME_HANDLE_TO_FD ioctl. + * + * Starting from kernel version 6.6, this bit is always set in &DRM_CAP_PRIME. */ #define DRM_PRIME_CAP_EXPORT 0x2 /** @@ -703,7 +710,8 @@ struct drm_gem_open { /** * DRM_CAP_ASYNC_PAGE_FLIP * - * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC. + * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC for legacy + * page-flips. */ #define DRM_CAP_ASYNC_PAGE_FLIP 0x7 /** @@ -753,17 +761,23 @@ struct drm_gem_open { /** * DRM_CAP_SYNCOBJ * - * If set to 1, the driver supports sync objects. See - * Documentation/gpu/drm-mm.rst, section "DRM Sync Objects". + * If set to 1, the driver supports sync objects. See :ref:`drm_sync_objects`. */ #define DRM_CAP_SYNCOBJ 0x13 /** * DRM_CAP_SYNCOBJ_TIMELINE * * If set to 1, the driver supports timeline operations on sync objects. See - * Documentation/gpu/drm-mm.rst, section "DRM Sync Objects". + * :ref:`drm_sync_objects`. */ #define DRM_CAP_SYNCOBJ_TIMELINE 0x14 +/** + * DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP + * + * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC for atomic + * commits. + */ +#define DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP 0x15 /* DRM_IOCTL_GET_CAP ioctl argument type */ struct drm_get_cap { @@ -833,6 +847,31 @@ struct drm_get_cap { */ #define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 5 +/** + * DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT + * + * Drivers for para-virtualized hardware (e.g. vmwgfx, qxl, virtio and + * virtualbox) have additional restrictions for cursor planes (thus + * making cursor planes on those drivers not truly universal,) e.g. + * they need cursor planes to act like one would expect from a mouse + * cursor and have correctly set hotspot properties. + * If this client cap is not set the DRM core will hide cursor plane on + * those virtualized drivers because not setting it implies that the + * client is not capable of dealing with those extra restictions. + * Clients which do set cursor hotspot and treat the cursor plane + * like a mouse cursor should set this property. + * The client must enable &DRM_CLIENT_CAP_ATOMIC first. + * + * Setting this property on drivers which do not special case + * cursor planes (i.e. non-virtualized drivers) will return + * EOPNOTSUPP, which can be used by userspace to gauge + * requirements of the hardware/drivers they're running on. + * + * This capability is always supported for atomic-capable virtualized + * drivers starting from kernel version 6.6. + */ +#define DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT 6 + /* DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ struct drm_set_client_cap { __u64 capability; @@ -884,6 +923,7 @@ struct drm_syncobj_transfer { #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0) #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1) #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2) /* wait for time point to become available */ +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE (1 << 3) /* set fence deadline to deadline_nsec */ struct drm_syncobj_wait { __u64 handles; /* absolute timeout */ @@ -892,6 +932,14 @@ struct drm_syncobj_wait { __u32 flags; __u32 first_signaled; /* only valid when not waiting all */ __u32 pad; + /** + * @deadline_nsec - fence deadline hint + * + * Deadline hint, in absolute CLOCK_MONOTONIC, to set on backing + * fence(s) if the DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE flag is + * set. + */ + __u64 deadline_nsec; }; struct drm_syncobj_timeline_wait { @@ -904,6 +952,35 @@ struct drm_syncobj_timeline_wait { __u32 flags; __u32 first_signaled; /* only valid when not waiting all */ __u32 pad; + /** + * @deadline_nsec - fence deadline hint + * + * Deadline hint, in absolute CLOCK_MONOTONIC, to set on backing + * fence(s) if the DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE flag is + * set. + */ + __u64 deadline_nsec; +}; + +/** + * struct drm_syncobj_eventfd + * @handle: syncobj handle. + * @flags: Zero to wait for the point to be signalled, or + * &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE to wait for a fence to be + * available for the point. + * @point: syncobj timeline point (set to zero for binary syncobjs). + * @fd: Existing eventfd to sent events to. + * @pad: Must be zero. + * + * Register an eventfd to be signalled by a syncobj. The eventfd counter will + * be incremented by one. + */ +struct drm_syncobj_eventfd { + __u32 handle; + __u32 flags; + __u64 point; + __s32 fd; + __u32 pad; }; @@ -969,6 +1046,19 @@ extern "C" { #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) #define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) #define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) +/** + * DRM_IOCTL_GEM_CLOSE - Close a GEM handle. + * + * GEM handles are not reference-counted by the kernel. User-space is + * responsible for managing their lifetime. For example, if user-space imports + * the same memory object twice on the same DRM file description, the same GEM + * handle is returned by both imports, and user-space needs to ensure + * &DRM_IOCTL_GEM_CLOSE is performed once only. The same situation can happen + * when a memory object is allocated, then exported and imported again on the + * same DRM file description. The &DRM_IOCTL_MODE_GETFB2 IOCTL is an exception + * and always returns fresh new GEM handles even if an existing GEM handle + * already refers to the same memory object before the IOCTL is performed. + */ #define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close) #define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink) #define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open) @@ -1009,7 +1099,37 @@ extern "C" { #define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock) #define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock) +/** + * DRM_IOCTL_PRIME_HANDLE_TO_FD - Convert a GEM handle to a DMA-BUF FD. + * + * User-space sets &drm_prime_handle.handle with the GEM handle to export and + * &drm_prime_handle.flags, and gets back a DMA-BUF file descriptor in + * &drm_prime_handle.fd. + * + * The export can fail for any driver-specific reason, e.g. because export is + * not supported for this specific GEM handle (but might be for others). + * + * Support for exporting DMA-BUFs is advertised via &DRM_PRIME_CAP_EXPORT. + */ #define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle) +/** + * DRM_IOCTL_PRIME_FD_TO_HANDLE - Convert a DMA-BUF FD to a GEM handle. + * + * User-space sets &drm_prime_handle.fd with a DMA-BUF file descriptor to + * import, and gets back a GEM handle in &drm_prime_handle.handle. + * &drm_prime_handle.flags is unused. + * + * If an existing GEM handle refers to the memory object backing the DMA-BUF, + * that GEM handle is returned. Therefore user-space which needs to handle + * arbitrary DMA-BUFs must have a user-space lookup data structure to manually + * reference-count duplicated GEM handles. For more information see + * &DRM_IOCTL_GEM_CLOSE. + * + * The import can fail for any driver-specific reason, e.g. because import is + * only supported for DMA-BUFs allocated on this DRM device. + * + * Support for importing DMA-BUFs is advertised via &DRM_PRIME_CAP_IMPORT. + */ #define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle) #define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) @@ -1047,10 +1167,40 @@ extern "C" { #define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob) #define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd) #define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd) +/** + * DRM_IOCTL_MODE_RMFB - Remove a framebuffer. + * + * This removes a framebuffer previously added via ADDFB/ADDFB2. The IOCTL + * argument is a framebuffer object ID. + * + * Warning: removing a framebuffer currently in-use on an enabled plane will + * disable that plane. The CRTC the plane is linked to may also be disabled + * (depending on driver capabilities). + */ #define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int) #define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip) #define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd) +/** + * DRM_IOCTL_MODE_CREATE_DUMB - Create a new dumb buffer object. + * + * KMS dumb buffers provide a very primitive way to allocate a buffer object + * suitable for scanout and map it for software rendering. KMS dumb buffers are + * not suitable for hardware-accelerated rendering nor video decoding. KMS dumb + * buffers are not suitable to be displayed on any other device than the KMS + * device where they were allocated from. Also see + * :ref:`kms_dumb_buffer_objects`. + * + * The IOCTL argument is a struct drm_mode_create_dumb. + * + * User-space is expected to create a KMS dumb buffer via this IOCTL, then add + * it as a KMS framebuffer via &DRM_IOCTL_MODE_ADDFB and map it via + * &DRM_IOCTL_MODE_MAP_DUMB. + * + * &DRM_CAP_DUMB_BUFFER indicates whether this IOCTL is supported. + * &DRM_CAP_DUMB_PREFERRED_DEPTH and &DRM_CAP_DUMB_PREFER_SHADOW indicate + * driver preferences for dumb buffers. + */ #define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb) #define DRM_IOCTL_MODE_MAP_DUMB DRM_IOWR(0xB3, struct drm_mode_map_dumb) #define DRM_IOCTL_MODE_DESTROY_DUMB DRM_IOWR(0xB4, struct drm_mode_destroy_dumb) @@ -1083,8 +1233,58 @@ extern "C" { #define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct drm_syncobj_transfer) #define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL DRM_IOWR(0xCD, struct drm_syncobj_timeline_array) +/** + * DRM_IOCTL_MODE_GETFB2 - Get framebuffer metadata. + * + * This queries metadata about a framebuffer. User-space fills + * &drm_mode_fb_cmd2.fb_id as the input, and the kernels fills the rest of the + * struct as the output. + * + * If the client is DRM master or has &CAP_SYS_ADMIN, &drm_mode_fb_cmd2.handles + * will be filled with GEM buffer handles. Fresh new GEM handles are always + * returned, even if another GEM handle referring to the same memory object + * already exists on the DRM file description. The caller is responsible for + * removing the new handles, e.g. via the &DRM_IOCTL_GEM_CLOSE IOCTL. The same + * new handle will be returned for multiple planes in case they use the same + * memory object. Planes are valid until one has a zero handle -- this can be + * used to compute the number of planes. + * + * Otherwise, &drm_mode_fb_cmd2.handles will be zeroed and planes are valid + * until one has a zero &drm_mode_fb_cmd2.pitches. + * + * If the framebuffer has a format modifier, &DRM_MODE_FB_MODIFIERS will be set + * in &drm_mode_fb_cmd2.flags and &drm_mode_fb_cmd2.modifier will contain the + * modifier. Otherwise, user-space must ignore &drm_mode_fb_cmd2.modifier. + * + * To obtain DMA-BUF FDs for each plane without leaking GEM handles, user-space + * can export each handle via &DRM_IOCTL_PRIME_HANDLE_TO_FD, then immediately + * close each unique handle via &DRM_IOCTL_GEM_CLOSE, making sure to not + * double-close handles which are specified multiple times in the array. + */ #define DRM_IOCTL_MODE_GETFB2 DRM_IOWR(0xCE, struct drm_mode_fb_cmd2) +#define DRM_IOCTL_SYNCOBJ_EVENTFD DRM_IOWR(0xCF, struct drm_syncobj_eventfd) + +/** + * DRM_IOCTL_MODE_CLOSEFB - Close a framebuffer. + * + * This closes a framebuffer previously added via ADDFB/ADDFB2. The IOCTL + * argument is a framebuffer object ID. + * + * This IOCTL is similar to &DRM_IOCTL_MODE_RMFB, except it doesn't disable + * planes and CRTCs. As long as the framebuffer is used by a plane, it's kept + * alive. When the plane no longer uses the framebuffer (because the + * framebuffer is replaced with another one, or the plane is disabled), the + * framebuffer is cleaned up. + * + * This is useful to implement flicker-free transitions between two processes. + * + * Depending on the threat model, user-space may want to ensure that the + * framebuffer doesn't expose any sensitive user information: closed + * framebuffers attached to a plane can be read back by the next DRM master. + */ +#define DRM_IOCTL_MODE_CLOSEFB DRM_IOWR(0xD0, struct drm_mode_closefb) + /* * Device specific ioctls should only be in their respective headers * The device specific ioctl range is from 0x40 to 0x9f. @@ -1096,25 +1296,50 @@ extern "C" { #define DRM_COMMAND_BASE 0x40 #define DRM_COMMAND_END 0xA0 -/* - * Header for events written back to userspace on the drm fd. The - * type defines the type of event, the length specifies the total - * length of the event (including the header), and user_data is - * typically a 64 bit value passed with the ioctl that triggered the - * event. A read on the drm fd will always only return complete - * events, that is, if for example the read buffer is 100 bytes, and - * there are two 64 byte events pending, only one will be returned. - * - * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and - * up are chipset specific. +/** + * struct drm_event - Header for DRM events + * @type: event type. + * @length: total number of payload bytes (including header). + * + * This struct is a header for events written back to user-space on the DRM FD. + * A read on the DRM FD will always only return complete events: e.g. if the + * read buffer is 100 bytes large and there are two 64 byte events pending, + * only one will be returned. + * + * Event types 0 - 0x7fffffff are generic DRM events, 0x80000000 and + * up are chipset specific. Generic DRM events include &DRM_EVENT_VBLANK, + * &DRM_EVENT_FLIP_COMPLETE and &DRM_EVENT_CRTC_SEQUENCE. */ struct drm_event { __u32 type; __u32 length; }; +/** + * DRM_EVENT_VBLANK - vertical blanking event + * + * This event is sent in response to &DRM_IOCTL_WAIT_VBLANK with the + * &_DRM_VBLANK_EVENT flag set. + * + * The event payload is a struct drm_event_vblank. + */ #define DRM_EVENT_VBLANK 0x01 +/** + * DRM_EVENT_FLIP_COMPLETE - page-flip completion event + * + * This event is sent in response to an atomic commit or legacy page-flip with + * the &DRM_MODE_PAGE_FLIP_EVENT flag set. + * + * The event payload is a struct drm_event_vblank. + */ #define DRM_EVENT_FLIP_COMPLETE 0x02 +/** + * DRM_EVENT_CRTC_SEQUENCE - CRTC sequence event + * + * This event is sent in response to &DRM_IOCTL_CRTC_QUEUE_SEQUENCE. + * + * The event payload is a struct drm_event_crtc_sequence. + */ #define DRM_EVENT_CRTC_SEQUENCE 0x03 struct drm_event_vblank { Index: xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c diff -u xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c:1.22 xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c:1.23 --- xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c:1.22 Sat Nov 12 02:07:08 2022 +++ xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c Thu Jul 4 09:22:57 2024 @@ -3590,13 +3590,9 @@ drm_intel_bufmgr_gem_init(int fd, int ba bufmgr_gem->gen = 6; else if (IS_GEN7(bufmgr_gem->pci_device)) bufmgr_gem->gen = 7; - else if (IS_GEN8(bufmgr_gem->pci_device)) + else + /* Treat all further unmatched platforms the same as gen8 */ bufmgr_gem->gen = 8; - else if (!intel_get_genx(bufmgr_gem->pci_device, &bufmgr_gem->gen)) { - free(bufmgr_gem); - bufmgr_gem = NULL; - goto exit; - } if (IS_GEN3(bufmgr_gem->pci_device) && bufmgr_gem->gtt_size > 256*1024*1024) { Index: xsrc/external/mit/libdrm/dist/intel/uthash.h diff -u xsrc/external/mit/libdrm/dist/intel/uthash.h:1.2 xsrc/external/mit/libdrm/dist/intel/uthash.h:1.3 --- xsrc/external/mit/libdrm/dist/intel/uthash.h:1.2 Mon Mar 6 23:11:39 2017 +++ xsrc/external/mit/libdrm/dist/intel/uthash.h Thu Jul 4 09:22:57 2024 @@ -648,11 +648,11 @@ do { #define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL) #define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL) #define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) -#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) +#ifdef HAVE_BIG_ENDIAN #define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) #define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) #define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) -#else /* assume little endian non-intel */ +#else /* little endian non-intel */ #define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) #define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) #define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) Index: xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c diff -u xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c:1.11 xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c:1.12 --- xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c:1.11 Thu Jan 10 08:59:43 2019 +++ xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c Thu Jul 4 09:22:57 2024 @@ -2205,6 +2205,7 @@ static int cik_surface_sanity(struct rad break; case RADEON_SURF_MODE_LINEAR_ALIGNED: default: + *stencil_tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED; *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED; } Index: xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c diff -u xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c:1.19 xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c:1.20 --- xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c:1.19 Sat Nov 12 02:07:08 2022 +++ xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c Thu Jul 4 09:22:57 2024 @@ -70,6 +70,7 @@ static enum util_fill_pattern primary_fill = UTIL_PATTERN_SMPTE; static enum util_fill_pattern secondary_fill = UTIL_PATTERN_TILES; +static drmModeModeInfo user_mode; struct crtc { drmModeCrtc *crtc; @@ -128,6 +129,7 @@ struct device { int use_atomic; drmModeAtomicReq *req; + int32_t writeback_fence_fd; }; static inline int64_t U642I64(uint64_t val) @@ -137,8 +139,19 @@ static inline int64_t U642I64(uint64_t v static float mode_vrefresh(drmModeModeInfo *mode) { - return mode->clock * 1000.00 - / (mode->htotal * mode->vtotal); + unsigned int num, den; + + num = mode->clock; + den = mode->htotal * mode->vtotal; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + num *= 2; + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) + den *= 2; + if (mode->vscan > 1) + den *= mode->vscan; + + return num * 1000.00 / den; } #define bit_name_fn(res) \ @@ -317,7 +330,7 @@ static void dump_in_formats(struct devic printf(": "); } - printf(" %s", modifier_to_string(iter.mod)); + printf(" %s(0x%"PRIx64")", modifier_to_string(iter.mod), iter.mod); } printf("\n"); @@ -804,13 +817,15 @@ struct pipe_arg { unsigned int num_cons; uint32_t crtc_id; char mode_str[64]; - char format_str[5]; + char format_str[8]; /* need to leave room for "_BE" and terminating \0 */ float vrefresh; unsigned int fourcc; drmModeModeInfo *mode; struct crtc *crtc; unsigned int fb_id[2], current_fb_id; struct timeval start; + unsigned int out_fb_id; + struct bo *out_bo; int swap_count; }; @@ -826,7 +841,7 @@ struct plane_arg { unsigned int old_fb_id; struct bo *bo; struct bo *old_bo; - char format_str[5]; /* need to leave room for terminating \0 */ + char format_str[8]; /* need to leave room for "_BE" and terminating \0 */ unsigned int fourcc; }; @@ -839,7 +854,25 @@ connector_find_mode(struct device *dev, int i; connector = get_connector_by_id(dev, con_id); - if (!connector || !connector->count_modes) + if (!connector) + return NULL; + + if (strchr(mode_str, ',')) { + i = sscanf(mode_str, "%hu,%hu,%hu,%hu,%hu,%hu,%hu,%hu", + &user_mode.hdisplay, &user_mode.hsync_start, + &user_mode.hsync_end, &user_mode.htotal, + &user_mode.vdisplay, &user_mode.vsync_start, + &user_mode.vsync_end, &user_mode.vtotal); + if (i == 8) { + user_mode.clock = roundf(user_mode.htotal * user_mode.vtotal * vrefresh / 1000); + user_mode.vrefresh = roundf(vrefresh); + snprintf(user_mode.name, sizeof(user_mode.name), "custom%dx%d", user_mode.hdisplay, user_mode.vdisplay); + + return &user_mode; + } + } + + if (!connector->count_modes) return NULL; /* Pick by Index */ @@ -1040,7 +1073,7 @@ static bool set_property(struct device * 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)); + obj_type, p->obj_id, p->name, p->value, strerror(-ret)); return true; } @@ -1116,15 +1149,23 @@ static bool add_property_optional(struct static void set_gamma(struct device *dev, unsigned crtc_id, unsigned fourcc) { unsigned blob_id = 0; + const struct util_format_info *info; /* TODO: support 1024-sized LUTs, when the use-case arises */ struct drm_color_lut gamma_lut[256]; int i, ret; - if (fourcc == DRM_FORMAT_C8) { - /* TODO: Add C8 support for more patterns */ - util_smpte_c8_gamma(256, gamma_lut); + info = util_format_info_find(fourcc); + if (info->ncolors) { + memset(gamma_lut, 0, sizeof(gamma_lut)); + /* TODO: Add index support for more patterns */ + util_smpte_fill_lut(info->ncolors, gamma_lut); drmModeCreatePropertyBlob(dev->fd, gamma_lut, sizeof(gamma_lut), &blob_id); } else { + /* + * Initialize gamma_lut to a linear table for the legacy API below. + * The modern property API resets to a linear/pass-thru table if blob_id + * is 0, hence no PropertyBlob is created here. + */ for (i = 0; i < 256; i++) { gamma_lut[i].red = gamma_lut[i].green = @@ -1135,6 +1176,7 @@ static void set_gamma(struct device *dev add_property_optional(dev, crtc_id, "DEGAMMA_LUT", 0); add_property_optional(dev, crtc_id, "CTM", 0); if (!add_property_optional(dev, crtc_id, "GAMMA_LUT", blob_id)) { + /* If we can't add the GAMMA_LUT property, try the legacy API. */ uint16_t r[256], g[256], b[256]; for (i = 0; i < 256; i++) { @@ -1144,7 +1186,7 @@ static void set_gamma(struct device *dev } ret = drmModeCrtcSetGamma(dev->fd, crtc_id, 256, r, g, b); - if (ret) + if (ret && errno != ENOSYS) fprintf(stderr, "failed to set gamma: %s\n", strerror(errno)); } } @@ -1441,6 +1483,24 @@ static int pipe_resolve_connectors(struc return 0; } +static bool pipe_has_writeback_connector(struct device *dev, struct pipe_arg *pipes, + unsigned int count) +{ + drmModeConnector *connector; + unsigned int i, j; + + for (j = 0; j < count; j++) { + struct pipe_arg *pipe = &pipes[j]; + + for (i = 0; i < pipe->num_cons; i++) { + connector = get_connector_by_id(dev, pipe->con_ids[i]); + if (connector && connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) + return true; + } + } + return false; +} + static int pipe_attempt_connector(struct device *dev, drmModeConnector *con, struct pipe_arg *pipe) { @@ -1503,7 +1563,8 @@ static int pipe_find_preferred(struct de for (i = 0; i < res->count_connectors; i++) { con = res->connectors[i].connector; - if (!con || con->connection != DRM_MODE_CONNECTED) + if (!con || con->connection != DRM_MODE_CONNECTED || + con->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) continue; connected++; } @@ -1550,32 +1611,35 @@ static struct plane *get_primary_plane_b return NULL; } -static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count) +static unsigned int set_mode(struct device *dev, struct pipe_arg **pipe_args, unsigned int count) { unsigned int i, j; int ret, x = 0; int preferred = count == 0; + struct pipe_arg *pipes; - for (i = 0; i < count; i++) { - struct pipe_arg *pipe = &pipes[i]; - - ret = pipe_resolve_connectors(dev, pipe); - if (ret < 0) - return; - - ret = pipe_find_crtc_and_mode(dev, pipe); - if (ret < 0) - continue; - } if (preferred) { - struct pipe_arg *pipe_args; - - count = pipe_find_preferred(dev, &pipe_args); + count = pipe_find_preferred(dev, pipe_args); if (!count) { fprintf(stderr, "can't find any preferred connector/mode.\n"); - return; + return 0; + } + + pipes = *pipe_args; + } else { + pipes = *pipe_args; + + for (i = 0; i < count; i++) { + struct pipe_arg *pipe = &pipes[i]; + + ret = pipe_resolve_connectors(dev, pipe); + if (ret < 0) + return 0; + + ret = pipe_find_crtc_and_mode(dev, pipe); + if (ret < 0) + continue; } - pipes = pipe_args; } if (!dev->use_atomic) { @@ -1602,7 +1666,7 @@ static void set_mode(struct device *dev, if (bo_fb_create(dev->fd, pipes[0].fourcc, dev->mode.width, dev->mode.height, primary_fill, &dev->mode.bo, &dev->mode.fb_id)) - return; + return 0; } for (i = 0; i < count; i++) { @@ -1634,7 +1698,7 @@ static void set_mode(struct device *dev, if (ret) { fprintf(stderr, "failed to set mode: %s\n", strerror(errno)); - return; + return 0; } set_gamma(dev, pipe->crtc_id, pipe->fourcc); @@ -1660,6 +1724,77 @@ static void set_mode(struct device *dev, } } } + + return count; +} + +static void writeback_config(struct device *dev, struct pipe_arg *pipes, unsigned int count) +{ + drmModeConnector *connector; + unsigned int i, j; + + for (j = 0; j < count; j++) { + struct pipe_arg *pipe = &pipes[j]; + + for (i = 0; i < pipe->num_cons; i++) { + connector = get_connector_by_id(dev, pipe->con_ids[i]); + if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) { + if (!pipe->mode) { + fprintf(stderr, "no mode for writeback\n"); + return; + } + bo_fb_create(dev->fd, pipes[j].fourcc, + pipe->mode->hdisplay, pipe->mode->vdisplay, + UTIL_PATTERN_PLAIN, + &pipe->out_bo, &pipe->out_fb_id); + add_property(dev, pipe->con_ids[i], "WRITEBACK_FB_ID", + pipe->out_fb_id); + add_property(dev, pipe->con_ids[i], "WRITEBACK_OUT_FENCE_PTR", + (uintptr_t)(&dev->writeback_fence_fd)); + } + } + } +} + +static int poll_writeback_fence(int fd, int timeout) +{ + struct pollfd fds = { fd, POLLIN }; + int ret; + + do { + ret = poll(&fds, 1, timeout); + if (ret > 0) { + if (fds.revents & (POLLERR | POLLNVAL)) + return -EINVAL; + + return 0; + } else if (ret == 0) { + return -ETIMEDOUT; + } else { + ret = -errno; + if (ret == -EINTR || ret == -EAGAIN) + continue; + return ret; + } + } while (1); + +} + +static void dump_output_fb(struct device *dev, struct pipe_arg *pipes, char *dump_path, + unsigned int count) +{ + drmModeConnector *connector; + unsigned int i, j; + + for (j = 0; j < count; j++) { + struct pipe_arg *pipe = &pipes[j]; + + for (i = 0; i < pipe->num_cons; i++) { + connector = get_connector_by_id(dev, pipe->con_ids[i]); + if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) + bo_dump(pipe->out_bo, dump_path); + } + } } static void atomic_clear_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count) @@ -1897,8 +2032,9 @@ static int parse_connector(struct pipe_a } if (*p == '@') { - strncpy(pipe->format_str, p + 1, 4); - pipe->format_str[4] = '\0'; + len = sizeof(pipe->format_str) - 1; + strncpy(pipe->format_str, p + 1, len); + pipe->format_str[len] = '\0'; } pipe->fourcc = util_format_fourcc(pipe->format_str); @@ -1912,6 +2048,7 @@ static int parse_connector(struct pipe_a static int parse_plane(struct plane_arg *plane, const char *p) { + unsigned int len; char *end; plane->plane_id = strtoul(p, &end, 10); @@ -1950,8 +2087,9 @@ static int parse_plane(struct plane_arg } if (*end == '@') { - strncpy(plane->format_str, end + 1, 4); - plane->format_str[4] = '\0'; + len = sizeof(plane->format_str) - 1; + strncpy(plane->format_str, end + 1, len); + plane->format_str[len] = '\0'; } else { strcpy(plane->format_str, "XR24"); } @@ -1990,7 +2128,7 @@ static void parse_fill_patterns(char *ar static void usage(char *name) { - fprintf(stderr, "usage: %s [-acDdefMPpsCvrw]\n", name); + fprintf(stderr, "usage: %s [-acDdefMoPpsCvrw]\n", name); fprintf(stderr, "\n Query options:\n\n"); fprintf(stderr, "\t-c\tlist connectors\n"); @@ -1999,14 +2137,19 @@ static void usage(char *name) fprintf(stderr, "\t-p\tlist CRTCs and planes (pipes)\n"); fprintf(stderr, "\n Test options:\n\n"); - fprintf(stderr, "\t-P <plane_id>@<crtc_id>:<w>x<h>[+<x>+<y>][*<scale>][@<format>]\tset a plane\n"); - fprintf(stderr, "\t-s <connector_id>[,<connector_id>][@<crtc_id>]:[#<mode index>]<mode>[-<vrefresh>][@<format>]\tset a mode\n"); + fprintf(stderr, "\t-P <plane_id>@<crtc_id>:<w>x<h>[+<x>+<y>][*<scale>][@<format>]\tset a plane, see 'plane-topology'\n"); + fprintf(stderr, "\t-s <connector_id>[,<connector_id>][@<crtc_id>]:mode[@<format>]\tset a mode, see 'mode-topology'\n"); + fprintf(stderr, "\t\twhere mode can be specified as:\n"); + fprintf(stderr, "\t\t<hdisp>x<vdisp>[-<vrefresh>]\n"); + fprintf(stderr, "\t\t<hdisp>,<hss>,<hse>,<htot>,<vdisp>,<vss>,<vse>,<vtot>-<vrefresh>\n"); + fprintf(stderr, "\t\t#<mode index>\n"); fprintf(stderr, "\t-C\ttest hw cursor\n"); fprintf(stderr, "\t-v\ttest vsynced page flipping\n"); fprintf(stderr, "\t-r\tset the preferred mode for all connectors\n"); - fprintf(stderr, "\t-w <obj_id>:<prop_name>:<value>\tset property\n"); + fprintf(stderr, "\t-w <obj_id>:<prop_name>:<value>\tset property, see 'property'\n"); fprintf(stderr, "\t-a \tuse atomic API\n"); fprintf(stderr, "\t-F pattern1,pattern2\tspecify fill patterns\n"); + fprintf(stderr, "\t-o <desired file path> \t Dump writeback output buffer to file\n"); fprintf(stderr, "\n Generic options:\n\n"); fprintf(stderr, "\t-d\tdrop master after mode set\n"); @@ -2014,10 +2157,29 @@ static void usage(char *name) fprintf(stderr, "\t-D device\tuse the given device\n"); fprintf(stderr, "\n\tDefault is to dump all info.\n"); + + fprintf(stderr, "\n"); + fprintf(stderr, "Plane Topology is defined as:\n"); + fprintf(stderr, "\tplane-topology\t::= plane-id '@' crtc-id ':' width 'x' height ( <plane-offsets> )? ;\n"); + fprintf(stderr, "\tplane-offsets\t::= '+' x-offset '+' y-offset ( <plane-scale> )? ;\n"); + fprintf(stderr, "\tplane-scale\t::= '*' scale ( <plane-format> )? ;\n"); + fprintf(stderr, "\tplane-format\t::= '@' format ;\n"); + + fprintf(stderr, "\n"); + fprintf(stderr, "Mode Topology is defined as:\n"); + fprintf(stderr, "\tmode-topology\t::= connector-id ( ',' connector-id )* ( '@' crtc-id )? ':' <mode-selection> ( '@' format )? ;\n"); + fprintf(stderr, "\tmode-selection\t::= <indexed-mode> | <named-mode> | <custom-mode> ;\n"); + fprintf(stderr, "\tindexed-mode\t::= '#' mode-index ;\n"); + fprintf(stderr, "\tnamed-mode\t::= width 'x' height ( '-' vrefresh )? ;\n"); + fprintf(stderr, "\tcustom-mode\t::= hdisplay ',' hsyncstart ',' hsyncend ',' htotal ',' vdisplay ',' vsyncstart ',' vsyncend ',' vtotal '-' vrefresh ;\n"); + + fprintf(stderr, "\n"); + fprintf(stderr, "Property is defined as:\n"); + fprintf(stderr, "\tproperty\t::= object-id ':' property-name ':' value ;\n"); exit(0); } -static char optstr[] = "acdD:efF:M:P:ps:Cvrw:"; +static char optstr[] = "acdD:efF:M:P:ps:Cvrw:o:"; int main(int argc, char **argv) { @@ -2040,6 +2202,7 @@ int main(int argc, char **argv) struct property_arg *prop_args = NULL; unsigned int args = 0; int ret; + char *dump_path = NULL; memset(&dev, 0, sizeof dev); @@ -2078,6 +2241,9 @@ int main(int argc, char **argv) /* Preserve the default behaviour of dumping all information. */ args--; break; + case 'o': + dump_path = optarg; + break; case 'P': plane_args = realloc(plane_args, (plane_count + 1) * sizeof *plane_args); @@ -2143,8 +2309,8 @@ int main(int argc, char **argv) if (!args) encoders = connectors = crtcs = planes = framebuffers = 1; - if (test_vsync && !count) { - fprintf(stderr, "page flipping requires at least one -s option.\n"); + if (test_vsync && !count && !set_preferred) { + fprintf(stderr, "page flipping requires at least one -s or -r option.\n"); return -1; } if (set_preferred && count) { @@ -2152,17 +2318,13 @@ int main(int argc, char **argv) return -1; } - if (set_preferred && plane_count) { - fprintf(stderr, "cannot use -r (preferred) when -P (plane) is set\n"); - return -1; - } - dev.fd = util_open(device, module); if (dev.fd < 0) return -1; if (use_atomic) { ret = drmSetClientCap(dev.fd, DRM_CLIENT_CAP_ATOMIC, 1); + drmSetClientCap(dev.fd, DRM_CLIENT_CAP_WRITEBACK_CONNECTORS, 1); if (ret) { fprintf(stderr, "no atomic modesetting support: %s\n", strerror(errno)); drmClose(dev.fd); @@ -2186,12 +2348,13 @@ int main(int argc, char **argv) dump_resource(&dev, planes); dump_resource(&dev, framebuffers); + if (dev.use_atomic) + dev.req = drmModeAtomicAlloc(); + for (i = 0; i < prop_count; ++i) set_property(&dev, &prop_args[i]); if (dev.use_atomic) { - dev.req = drmModeAtomicAlloc(); - if (set_preferred || (count && plane_count)) { uint64_t cap = 0; @@ -2202,7 +2365,16 @@ int main(int argc, char **argv) } if (set_preferred || count) - set_mode(&dev, pipe_args, count); + count = set_mode(&dev, &pipe_args, count); + + if (dump_path) { + if (!pipe_has_writeback_connector(&dev, pipe_args, count)) { + fprintf(stderr, "No writeback connector found, can not dump.\n"); + return 1; + } + + writeback_config(&dev, pipe_args, count); + } if (plane_count) atomic_set_planes(&dev, plane_args, plane_count, false); @@ -2213,6 +2385,18 @@ int main(int argc, char **argv) return 1; } + /* + * Since only writeback connectors have an output fb, this should only be + * called for writeback. + */ + if (dump_path) { + ret = poll_writeback_fence(dev.writeback_fence_fd, 1000); + if (ret) + fprintf(stderr, "Poll for writeback error: %d. Skipping Dump.\n", + ret); + dump_output_fb(&dev, pipe_args, dump_path, count); + } + if (test_vsync) atomic_test_page_flip(&dev, pipe_args, plane_args, plane_count); @@ -2230,17 +2414,22 @@ int main(int argc, char **argv) if (count) atomic_clear_mode(&dev, pipe_args, count); + } - ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); - if (ret) - fprintf(stderr, "Atomic Commit failed\n"); + ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); + if (ret) + fprintf(stderr, "Atomic Commit failed\n"); - if (plane_count) - atomic_clear_FB(&dev, plane_args, plane_count); - } + if (count && plane_count) + atomic_clear_FB(&dev, plane_args, plane_count); drmModeAtomicFree(dev.req); } else { + if (dump_path) { + fprintf(stderr, "writeback / dump is only supported in atomic mode\n"); + return 1; + } + if (set_preferred || count || plane_count) { uint64_t cap = 0; @@ -2251,7 +2440,7 @@ int main(int argc, char **argv) } if (set_preferred || count) - set_mode(&dev, pipe_args, count); + count = set_mode(&dev, &pipe_args, count); if (plane_count) set_planes(&dev, plane_args, plane_count);