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);