Module Name: xsrc
Committed By: mrg
Date: Sat Mar 4 23:22:49 UTC 2017
Modified Files:
xsrc/external/mit/libdrm/dist: xf86drm.c xf86drm.h xf86drmMode.c
xf86drmMode.h
xsrc/external/mit/libdrm/dist/include/drm: drm.h i915_drm.h
xsrc/external/mit/libdrm/dist/intel: intel_bufmgr_gem.c
xsrc/external/mit/libdrm/dist/radeon: radeon_cs_gem.c radeon_surface.c
xsrc/external/mit/libdrm/dist/tests/modetest: modetest.c
xsrc/external/mit/pixman/dist/pixman: pixman-inlines.h pixman-mmx.c
pixman-private.h
Removed Files:
xsrc/external/mit/libdrm/dist/tests: dristat.c drmstat.c drmtest.c
drmtest.h getclient.c getstats.c getversion.c name_from_fd.c
openclose.c setversion.c updatedraw.c
Log Message:
merge libdrm 2.4.75 and pixman 0.34.0
To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 xsrc/external/mit/libdrm/dist/xf86drm.c
cvs rdiff -u -r1.6 -r1.7 xsrc/external/mit/libdrm/dist/xf86drm.h \
xsrc/external/mit/libdrm/dist/xf86drmMode.h
cvs rdiff -u -r1.10 -r1.11 xsrc/external/mit/libdrm/dist/xf86drmMode.c
cvs rdiff -u -r1.6 -r1.7 xsrc/external/mit/libdrm/dist/include/drm/drm.h
cvs rdiff -u -r1.4 -r1.5 xsrc/external/mit/libdrm/dist/include/drm/i915_drm.h
cvs rdiff -u -r1.12 -r1.13 \
xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c
cvs rdiff -u -r1.6 -r1.7 xsrc/external/mit/libdrm/dist/radeon/radeon_cs_gem.c
cvs rdiff -u -r1.8 -r1.9 \
xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c
cvs rdiff -u -r1.1.1.4 -r0 xsrc/external/mit/libdrm/dist/tests/dristat.c
cvs rdiff -u -r1.1.1.5 -r0 xsrc/external/mit/libdrm/dist/tests/drmstat.c
cvs rdiff -u -r1.1.1.3 -r0 xsrc/external/mit/libdrm/dist/tests/drmtest.c \
xsrc/external/mit/libdrm/dist/tests/getversion.c \
xsrc/external/mit/libdrm/dist/tests/name_from_fd.c \
xsrc/external/mit/libdrm/dist/tests/setversion.c
cvs rdiff -u -r1.1.1.1 -r0 xsrc/external/mit/libdrm/dist/tests/drmtest.h \
xsrc/external/mit/libdrm/dist/tests/openclose.c
cvs rdiff -u -r1.1.1.2 -r0 xsrc/external/mit/libdrm/dist/tests/getclient.c \
xsrc/external/mit/libdrm/dist/tests/getstats.c \
xsrc/external/mit/libdrm/dist/tests/updatedraw.c
cvs rdiff -u -r1.8 -r1.9 \
xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c
cvs rdiff -u -r1.3 -r1.4 \
xsrc/external/mit/pixman/dist/pixman/pixman-inlines.h
cvs rdiff -u -r1.2 -r1.3 xsrc/external/mit/pixman/dist/pixman/pixman-mmx.c
cvs rdiff -u -r1.5 -r1.6 \
xsrc/external/mit/pixman/dist/pixman/pixman-private.h
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/xf86drm.c
diff -u xsrc/external/mit/libdrm/dist/xf86drm.c:1.13 xsrc/external/mit/libdrm/dist/xf86drm.c:1.14
--- xsrc/external/mit/libdrm/dist/xf86drm.c:1.13 Fri Jan 13 04:24:01 2017
+++ xsrc/external/mit/libdrm/dist/xf86drm.c Sat Mar 4 23:22:48 2017
@@ -62,6 +62,10 @@
#endif
#include <math.h>
+/* Not all systems have MAP_FAILED defined */
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
#include "xf86drm.h"
#include "libdrm_macros.h"
@@ -99,9 +103,20 @@
#define DRM_MAJOR 226 /* Linux */
#endif
-/* Not all systems have MAP_FAILED defined */
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *)-1)
+#ifdef __OpenBSD__
+struct drm_pciinfo {
+ uint16_t domain;
+ uint8_t bus;
+ uint8_t dev;
+ uint8_t func;
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint16_t subvendor_id;
+ uint16_t subdevice_id;
+ uint8_t revision_id;
+};
+
+#define DRM_IOCTL_GET_PCIINFO DRM_IOR(0x15, struct drm_pciinfo)
#endif
#define DRM_MSG_VERBOSITY 3
@@ -2820,7 +2835,44 @@ static char *drmGetMinorNameForFD(int fd
out_close_dir:
closedir(sysdir);
#else
-#warning "Missing implementation of drmGetMinorNameForFD"
+ struct stat sbuf;
+ char buf[PATH_MAX + 1];
+ const char *dev_name;
+ unsigned int maj, min;
+ int n, base;
+
+ if (fstat(fd, &sbuf))
+ return NULL;
+
+ maj = major(sbuf.st_rdev);
+ min = minor(sbuf.st_rdev);
+
+ if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+ return NULL;
+
+ switch (type) {
+ case DRM_NODE_PRIMARY:
+ dev_name = DRM_DEV_NAME;
+ break;
+ case DRM_NODE_CONTROL:
+ dev_name = DRM_CONTROL_DEV_NAME;
+ break;
+ case DRM_NODE_RENDER:
+ dev_name = DRM_RENDER_DEV_NAME;
+ break;
+ default:
+ return NULL;
+ };
+
+ base = drmGetMinorBase(type);
+ if (base < 0)
+ return NULL;
+
+ n = snprintf(buf, sizeof(buf), dev_name, DRM_DIR_NAME, min - base);
+ if (n == -1 || n >= sizeof(buf))
+ return NULL;
+
+ return strdup(buf);
#endif
return NULL;
}
@@ -2835,6 +2887,50 @@ char *drmGetRenderDeviceNameFromFd(int f
return drmGetMinorNameForFD(fd, DRM_NODE_RENDER);
}
+#ifdef __linux__
+static char * DRM_PRINTFLIKE(2, 3)
+sysfs_uevent_get(const char *path, const char *fmt, ...)
+{
+ char filename[PATH_MAX + 1], *key, *line = NULL, *value = NULL;
+ size_t size = 0, len;
+ ssize_t num;
+ va_list ap;
+ FILE *fp;
+
+ va_start(ap, fmt);
+ num = vasprintf(&key, fmt, ap);
+ va_end(ap);
+ len = num;
+
+ snprintf(filename, sizeof(filename), "%s/uevent", path);
+
+ fp = fopen(filename, "r");
+ if (!fp) {
+ free(key);
+ return NULL;
+ }
+
+ while ((num = getline(&line, &size, fp)) >= 0) {
+ if ((strncmp(line, key, len) == 0) && (line[len] == '=')) {
+ char *start = line + len + 1, *end = line + num - 1;
+
+ if (*end != '\n')
+ end++;
+
+ value = strndup(start, end - start);
+ break;
+ }
+ }
+
+ free(line);
+ fclose(fp);
+
+ free(key);
+
+ return value;
+}
+#endif
+
static int drmParseSubsystemType(int maj, int min)
{
#ifdef __linux__
@@ -2855,7 +2951,18 @@ static int drmParseSubsystemType(int maj
if (strncmp(name, "/pci", 4) == 0)
return DRM_BUS_PCI;
+ if (strncmp(name, "/usb", 4) == 0)
+ return DRM_BUS_USB;
+
+ if (strncmp(name, "/platform", 9) == 0)
+ return DRM_BUS_PLATFORM;
+
+ if (strncmp(name, "/host1x", 7) == 0)
+ return DRM_BUS_HOST1X;
+
return -EINVAL;
+#elif defined(__OpenBSD__)
+ return DRM_BUS_PCI;
#else
#warning "Missing implementation of drmParseSubsystemType"
return -EINVAL;
@@ -2865,32 +2972,21 @@ static int drmParseSubsystemType(int maj
static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info)
{
#ifdef __linux__
- char path[PATH_MAX + 1];
- char data[128 + 1];
- char *str;
- int domain, bus, dev, func;
- int fd, ret;
+ unsigned int domain, bus, dev, func;
+ char path[PATH_MAX + 1], *value;
+ int num;
- snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/uevent", maj, min);
- fd = open(path, O_RDONLY);
- if (fd < 0)
- return -errno;
+ snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
- ret = read(fd, data, sizeof(data));
- data[128] = '\0';
- close(fd);
- if (ret < 0)
- return -errno;
+ value = sysfs_uevent_get(path, "PCI_SLOT_NAME");
+ if (!value)
+ return -ENOENT;
-#define TAG "PCI_SLOT_NAME="
- str = strstr(data, TAG);
- if (str == NULL)
- return -EINVAL;
+ num = sscanf(value, "%04x:%02x:%02x.%1u", &domain, &bus, &dev, &func);
+ free(value);
- if (sscanf(str, TAG "%04x:%02x:%02x.%1u",
- &domain, &bus, &dev, &func) != 4)
+ if (num != 4)
return -EINVAL;
-#undef TAG
info->domain = domain;
info->bus = bus;
@@ -2898,6 +2994,30 @@ static int drmParsePciBusInfo(int maj, i
info->func = func;
return 0;
+#elif defined(__OpenBSD__)
+ struct drm_pciinfo pinfo;
+ int fd, type;
+
+ type = drmGetMinorType(min);
+ if (type == -1)
+ return -ENODEV;
+
+ fd = drmOpenMinor(min, 0, type);
+ if (fd < 0)
+ return -errno;
+
+ if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) {
+ close(fd);
+ return -errno;
+ }
+ close(fd);
+
+ info->domain = pinfo.domain;
+ info->bus = pinfo.bus;
+ info->dev = pinfo.dev;
+ info->func = pinfo.func;
+
+ return 0;
#else
#warning "Missing implementation of drmParsePciBusInfo"
return -EINVAL;
@@ -2915,6 +3035,16 @@ static int drmCompareBusInfo(drmDevicePt
switch (a->bustype) {
case DRM_BUS_PCI:
return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo));
+
+ case DRM_BUS_USB:
+ return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo));
+
+ case DRM_BUS_PLATFORM:
+ return memcmp(a->businfo.platform, b->businfo.platform, sizeof(drmPlatformBusInfo));
+
+ case DRM_BUS_HOST1X:
+ return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo));
+
default:
break;
}
@@ -2948,15 +3078,55 @@ static int drmGetMaxNodeName(void)
3 /* length of the node number */;
}
-static int drmParsePciDeviceInfo(const char *d_name,
- drmPciDeviceInfoPtr device)
-{
#ifdef __linux__
+static int parse_separate_sysfs_files(int maj, int min,
+ drmPciDeviceInfoPtr device,
+ bool ignore_revision)
+{
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+ static const char *attrs[] = {
+ "revision", /* Older kernels are missing the file, so check for it first */
+ "vendor",
+ "device",
+ "subsystem_vendor",
+ "subsystem_device",
+ };
+ char path[PATH_MAX + 1];
+ unsigned int data[ARRAY_SIZE(attrs)];
+ FILE *fp;
+ int ret;
+
+ for (unsigned i = ignore_revision ? 1 : 0; i < ARRAY_SIZE(attrs); i++) {
+ snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/%s", maj, min,
+ attrs[i]);
+ fp = fopen(path, "r");
+ if (!fp)
+ return -errno;
+
+ ret = fscanf(fp, "%x", &data[i]);
+ fclose(fp);
+ if (ret != 1)
+ return -errno;
+
+ }
+
+ device->revision_id = ignore_revision ? 0xff : data[0] & 0xff;
+ device->vendor_id = data[1] & 0xffff;
+ device->device_id = data[2] & 0xffff;
+ device->subvendor_id = data[3] & 0xffff;
+ device->subdevice_id = data[4] & 0xffff;
+
+ return 0;
+}
+
+static int parse_config_sysfs_file(int maj, int min,
+ drmPciDeviceInfoPtr device)
+{
char path[PATH_MAX + 1];
unsigned char config[64];
int fd, ret;
- snprintf(path, PATH_MAX, "/sys/class/drm/%s/device/config", d_name);
+ snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/config", maj, min);
fd = open(path, O_RDONLY);
if (fd < 0)
return -errno;
@@ -2973,17 +3143,101 @@ static int drmParsePciDeviceInfo(const c
device->subdevice_id = config[46] | (config[47] << 8);
return 0;
+}
+#endif
+
+static int drmParsePciDeviceInfo(int maj, int min,
+ drmPciDeviceInfoPtr device,
+ uint32_t flags)
+{
+#ifdef __linux__
+ if (!(flags & DRM_DEVICE_GET_PCI_REVISION))
+ return parse_separate_sysfs_files(maj, min, device, true);
+
+ if (parse_separate_sysfs_files(maj, min, device, false))
+ return parse_config_sysfs_file(maj, min, device);
+
+ return 0;
+#elif defined(__OpenBSD__)
+ struct drm_pciinfo pinfo;
+ int fd, type;
+
+ type = drmGetMinorType(min);
+ if (type == -1)
+ return -ENODEV;
+
+ fd = drmOpenMinor(min, 0, type);
+ if (fd < 0)
+ return -errno;
+
+ if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) {
+ close(fd);
+ return -errno;
+ }
+ close(fd);
+
+ device->vendor_id = pinfo.vendor_id;
+ device->device_id = pinfo.device_id;
+ device->revision_id = pinfo.revision_id;
+ device->subvendor_id = pinfo.subvendor_id;
+ device->subdevice_id = pinfo.subdevice_id;
+
+ return 0;
#else
#warning "Missing implementation of drmParsePciDeviceInfo"
return -EINVAL;
#endif
}
+static void drmFreePlatformDevice(drmDevicePtr device)
+{
+ if (device->deviceinfo.platform) {
+ if (device->deviceinfo.platform->compatible) {
+ char **compatible = device->deviceinfo.platform->compatible;
+
+ while (*compatible) {
+ free(*compatible);
+ compatible++;
+ }
+
+ free(device->deviceinfo.platform->compatible);
+ }
+ }
+}
+
+static void drmFreeHost1xDevice(drmDevicePtr device)
+{
+ if (device->deviceinfo.host1x) {
+ if (device->deviceinfo.host1x->compatible) {
+ char **compatible = device->deviceinfo.host1x->compatible;
+
+ while (*compatible) {
+ free(*compatible);
+ compatible++;
+ }
+
+ free(device->deviceinfo.host1x->compatible);
+ }
+ }
+}
+
void drmFreeDevice(drmDevicePtr *device)
{
if (device == NULL)
return;
+ if (*device) {
+ switch ((*device)->bustype) {
+ case DRM_BUS_PLATFORM:
+ drmFreePlatformDevice(*device);
+ break;
+
+ case DRM_BUS_HOST1X:
+ drmFreeHost1xDevice(*device);
+ break;
+ }
+ }
+
free(*device);
*device = NULL;
}
@@ -3000,56 +3254,402 @@ void drmFreeDevices(drmDevicePtr devices
drmFreeDevice(&devices[i]);
}
-static int drmProcessPciDevice(drmDevicePtr *device, const char *d_name,
- const char *node, int node_type,
- int maj, int min, bool fetch_deviceinfo)
+static drmDevicePtr drmDeviceAlloc(unsigned int type, const char *node,
+ size_t bus_size, size_t device_size,
+ char **ptrp)
{
- const int max_node_str = ALIGN(drmGetMaxNodeName(), sizeof(void *));
- int ret, i;
- char *addr;
+ size_t max_node_length, extra, size;
+ drmDevicePtr device;
+ unsigned int i;
+ char *ptr;
- *device = calloc(1, sizeof(drmDevice) +
- (DRM_NODE_MAX * (sizeof(void *) + max_node_str)) +
- sizeof(drmPciBusInfo) +
- sizeof(drmPciDeviceInfo));
- if (!*device)
- return -ENOMEM;
+ max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *));
+ extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length);
+
+ size = sizeof(*device) + extra + bus_size + device_size;
- addr = (char*)*device;
+ device = calloc(1, size);
+ if (!device)
+ return NULL;
+
+ device->available_nodes = 1 << type;
- (*device)->bustype = DRM_BUS_PCI;
- (*device)->available_nodes = 1 << node_type;
+ ptr = (char *)device + sizeof(*device);
+ device->nodes = (char **)ptr;
- addr += sizeof(drmDevice);
- (*device)->nodes = (char**)addr;
+ ptr += DRM_NODE_MAX * sizeof(void *);
- addr += DRM_NODE_MAX * sizeof(void *);
for (i = 0; i < DRM_NODE_MAX; i++) {
- (*device)->nodes[i] = addr;
- addr += max_node_str;
+ device->nodes[i] = ptr;
+ ptr += max_node_length;
}
- memcpy((*device)->nodes[node_type], node, max_node_str);
- (*device)->businfo.pci = (drmPciBusInfoPtr)addr;
+ memcpy(device->nodes[type], node, max_node_length);
+
+ *ptrp = ptr;
+
+ return device;
+}
- ret = drmParsePciBusInfo(maj, min, (*device)->businfo.pci);
+static int drmProcessPciDevice(drmDevicePtr *device,
+ const char *node, int node_type,
+ int maj, int min, bool fetch_deviceinfo,
+ uint32_t flags)
+{
+ drmDevicePtr dev;
+ char *addr;
+ int ret;
+
+ dev = drmDeviceAlloc(node_type, node, sizeof(drmPciBusInfo),
+ sizeof(drmPciDeviceInfo), &addr);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->bustype = DRM_BUS_PCI;
+
+ dev->businfo.pci = (drmPciBusInfoPtr)addr;
+
+ ret = drmParsePciBusInfo(maj, min, dev->businfo.pci);
if (ret)
goto free_device;
// Fetch the device info if the user has requested it
if (fetch_deviceinfo) {
addr += sizeof(drmPciBusInfo);
- (*device)->deviceinfo.pci = (drmPciDeviceInfoPtr)addr;
+ dev->deviceinfo.pci = (drmPciDeviceInfoPtr)addr;
- ret = drmParsePciDeviceInfo(d_name, (*device)->deviceinfo.pci);
+ ret = drmParsePciDeviceInfo(maj, min, dev->deviceinfo.pci, flags);
if (ret)
goto free_device;
}
+
+ *device = dev;
+
return 0;
free_device:
- free(*device);
- *device = NULL;
+ free(dev);
+ return ret;
+}
+
+static int drmParseUsbBusInfo(int maj, int min, drmUsbBusInfoPtr info)
+{
+#ifdef __linux__
+ char path[PATH_MAX + 1], *value;
+ unsigned int bus, dev;
+ int ret;
+
+ snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+
+ value = sysfs_uevent_get(path, "BUSNUM");
+ if (!value)
+ return -ENOENT;
+
+ ret = sscanf(value, "%03u", &bus);
+ free(value);
+
+ if (ret <= 0)
+ return -errno;
+
+ value = sysfs_uevent_get(path, "DEVNUM");
+ if (!value)
+ return -ENOENT;
+
+ ret = sscanf(value, "%03u", &dev);
+ free(value);
+
+ if (ret <= 0)
+ return -errno;
+
+ info->bus = bus;
+ info->dev = dev;
+
+ return 0;
+#else
+#warning "Missing implementation of drmParseUsbBusInfo"
+ return -EINVAL;
+#endif
+}
+
+static int drmParseUsbDeviceInfo(int maj, int min, drmUsbDeviceInfoPtr info)
+{
+#ifdef __linux__
+ char path[PATH_MAX + 1], *value;
+ unsigned int vendor, product;
+ int ret;
+
+ snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+
+ value = sysfs_uevent_get(path, "PRODUCT");
+ if (!value)
+ return -ENOENT;
+
+ ret = sscanf(value, "%x/%x", &vendor, &product);
+ free(value);
+
+ if (ret <= 0)
+ return -errno;
+
+ info->vendor = vendor;
+ info->product = product;
+
+ return 0;
+#else
+#warning "Missing implementation of drmParseUsbDeviceInfo"
+ return -EINVAL;
+#endif
+}
+
+static int drmProcessUsbDevice(drmDevicePtr *device, const char *node,
+ int node_type, int maj, int min,
+ bool fetch_deviceinfo, uint32_t flags)
+{
+ drmDevicePtr dev;
+ char *ptr;
+ int ret;
+
+ dev = drmDeviceAlloc(node_type, node, sizeof(drmUsbBusInfo),
+ sizeof(drmUsbDeviceInfo), &ptr);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->bustype = DRM_BUS_USB;
+
+ dev->businfo.usb = (drmUsbBusInfoPtr)ptr;
+
+ ret = drmParseUsbBusInfo(maj, min, dev->businfo.usb);
+ if (ret < 0)
+ goto free_device;
+
+ if (fetch_deviceinfo) {
+ ptr += sizeof(drmUsbBusInfo);
+ dev->deviceinfo.usb = (drmUsbDeviceInfoPtr)ptr;
+
+ ret = drmParseUsbDeviceInfo(maj, min, dev->deviceinfo.usb);
+ if (ret < 0)
+ goto free_device;
+ }
+
+ *device = dev;
+
+ return 0;
+
+free_device:
+ free(dev);
+ return ret;
+}
+
+static int drmParsePlatformBusInfo(int maj, int min, drmPlatformBusInfoPtr info)
+{
+#ifdef __linux__
+ char path[PATH_MAX + 1], *name;
+
+ snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+
+ name = sysfs_uevent_get(path, "OF_FULLNAME");
+ if (!name)
+ return -ENOENT;
+
+ strncpy(info->fullname, name, DRM_PLATFORM_DEVICE_NAME_LEN);
+ info->fullname[DRM_PLATFORM_DEVICE_NAME_LEN - 1] = '\0';
+ free(name);
+
+ return 0;
+#else
+#warning "Missing implementation of drmParsePlatformBusInfo"
+ return -EINVAL;
+#endif
+}
+
+static int drmParsePlatformDeviceInfo(int maj, int min,
+ drmPlatformDeviceInfoPtr info)
+{
+#ifdef __linux__
+ char path[PATH_MAX + 1], *value;
+ unsigned int count, i;
+ int err;
+
+ snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+
+ value = sysfs_uevent_get(path, "OF_COMPATIBLE_N");
+ if (!value)
+ return -ENOENT;
+
+ sscanf(value, "%u", &count);
+ free(value);
+
+ info->compatible = calloc(count + 1, sizeof(*info->compatible));
+ if (!info->compatible)
+ return -ENOMEM;
+
+ for (i = 0; i < count; i++) {
+ value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i);
+ if (!value) {
+ err = -ENOENT;
+ goto free;
+ }
+
+ info->compatible[i] = value;
+ }
+
+ return 0;
+
+free:
+ while (i--)
+ free(info->compatible[i]);
+
+ free(info->compatible);
+ return err;
+#else
+#warning "Missing implementation of drmParsePlatformDeviceInfo"
+ return -EINVAL;
+#endif
+}
+
+static int drmProcessPlatformDevice(drmDevicePtr *device,
+ const char *node, int node_type,
+ int maj, int min, bool fetch_deviceinfo,
+ uint32_t flags)
+{
+ drmDevicePtr dev;
+ char *ptr;
+ int ret;
+
+ dev = drmDeviceAlloc(node_type, node, sizeof(drmPlatformBusInfo),
+ sizeof(drmPlatformDeviceInfo), &ptr);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->bustype = DRM_BUS_PLATFORM;
+
+ dev->businfo.platform = (drmPlatformBusInfoPtr)ptr;
+
+ ret = drmParsePlatformBusInfo(maj, min, dev->businfo.platform);
+ if (ret < 0)
+ goto free_device;
+
+ if (fetch_deviceinfo) {
+ ptr += sizeof(drmPlatformBusInfo);
+ dev->deviceinfo.platform = (drmPlatformDeviceInfoPtr)ptr;
+
+ ret = drmParsePlatformDeviceInfo(maj, min, dev->deviceinfo.platform);
+ if (ret < 0)
+ goto free_device;
+ }
+
+ *device = dev;
+
+ return 0;
+
+free_device:
+ free(dev);
+ return ret;
+}
+
+static int drmParseHost1xBusInfo(int maj, int min, drmHost1xBusInfoPtr info)
+{
+#ifdef __linux__
+ char path[PATH_MAX + 1], *name;
+
+ snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+
+ name = sysfs_uevent_get(path, "OF_FULLNAME");
+ if (!name)
+ return -ENOENT;
+
+ strncpy(info->fullname, name, DRM_HOST1X_DEVICE_NAME_LEN);
+ info->fullname[DRM_HOST1X_DEVICE_NAME_LEN - 1] = '\0';
+ free(name);
+
+ return 0;
+#else
+#warning "Missing implementation of drmParseHost1xBusInfo"
+ return -EINVAL;
+#endif
+}
+
+static int drmParseHost1xDeviceInfo(int maj, int min,
+ drmHost1xDeviceInfoPtr info)
+{
+#ifdef __linux__
+ char path[PATH_MAX + 1], *value;
+ unsigned int count, i;
+ int err;
+
+ snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+
+ value = sysfs_uevent_get(path, "OF_COMPATIBLE_N");
+ if (!value)
+ return -ENOENT;
+
+ sscanf(value, "%u", &count);
+ free(value);
+
+ info->compatible = calloc(count + 1, sizeof(*info->compatible));
+ if (!info->compatible)
+ return -ENOMEM;
+
+ for (i = 0; i < count; i++) {
+ value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i);
+ if (!value) {
+ err = -ENOENT;
+ goto free;
+ }
+
+ info->compatible[i] = value;
+ }
+
+ return 0;
+
+free:
+ while (i--)
+ free(info->compatible[i]);
+
+ free(info->compatible);
+ return err;
+#else
+#warning "Missing implementation of drmParseHost1xDeviceInfo"
+ return -EINVAL;
+#endif
+}
+
+static int drmProcessHost1xDevice(drmDevicePtr *device,
+ const char *node, int node_type,
+ int maj, int min, bool fetch_deviceinfo,
+ uint32_t flags)
+{
+ drmDevicePtr dev;
+ char *ptr;
+ int ret;
+
+ dev = drmDeviceAlloc(node_type, node, sizeof(drmHost1xBusInfo),
+ sizeof(drmHost1xDeviceInfo), &ptr);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->bustype = DRM_BUS_HOST1X;
+
+ dev->businfo.host1x = (drmHost1xBusInfoPtr)ptr;
+
+ ret = drmParseHost1xBusInfo(maj, min, dev->businfo.host1x);
+ if (ret < 0)
+ goto free_device;
+
+ if (fetch_deviceinfo) {
+ ptr += sizeof(drmHost1xBusInfo);
+ dev->deviceinfo.host1x = (drmHost1xDeviceInfoPtr)ptr;
+
+ ret = drmParseHost1xDeviceInfo(maj, min, dev->deviceinfo.host1x);
+ if (ret < 0)
+ goto free_device;
+ }
+
+ *device = dev;
+
+ return 0;
+
+free_device:
+ free(dev);
return ret;
}
@@ -3075,17 +3675,93 @@ static void drmFoldDuplicatedDevices(drm
}
}
+/* Check that the given flags are valid returning 0 on success */
+static int
+drm_device_validate_flags(uint32_t flags)
+{
+ return (flags & ~DRM_DEVICE_GET_PCI_REVISION);
+}
+
/**
* Get information about the opened drm device
*
* \param fd file descriptor of the drm device
+ * \param flags feature/behaviour bitmask
* \param device the address of a drmDevicePtr where the information
* will be allocated in stored
*
* \return zero on success, negative error code otherwise.
+ *
+ * \note Unlike drmGetDevice it does not retrieve the pci device revision field
+ * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set.
*/
-int drmGetDevice(int fd, drmDevicePtr *device)
+int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device)
{
+#ifdef __OpenBSD__
+ /*
+ * DRI device nodes on OpenBSD are not in their own directory, they reside
+ * in /dev along with a large number of statically generated /dev nodes.
+ * Avoid stat'ing all of /dev needlessly by implementing this custom path.
+ */
+ drmDevicePtr d;
+ struct stat sbuf;
+ char node[PATH_MAX + 1];
+ const char *dev_name;
+ int node_type, subsystem_type;
+ int maj, min, n, ret, base;
+
+ if (fd == -1 || device == NULL)
+ return -EINVAL;
+
+ if (fstat(fd, &sbuf))
+ return -errno;
+
+ maj = major(sbuf.st_rdev);
+ min = minor(sbuf.st_rdev);
+
+ if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+ return -EINVAL;
+
+ node_type = drmGetMinorType(min);
+ if (node_type == -1)
+ return -ENODEV;
+
+ switch (node_type) {
+ case DRM_NODE_PRIMARY:
+ dev_name = DRM_DEV_NAME;
+ break;
+ case DRM_NODE_CONTROL:
+ dev_name = DRM_CONTROL_DEV_NAME;
+ break;
+ case DRM_NODE_RENDER:
+ dev_name = DRM_RENDER_DEV_NAME;
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ base = drmGetMinorBase(node_type);
+ if (base < 0)
+ return -EINVAL;
+
+ n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min - base);
+ if (n == -1 || n >= PATH_MAX)
+ return -errno;
+ if (stat(node, &sbuf))
+ return -EINVAL;
+
+ subsystem_type = drmParseSubsystemType(maj, min);
+ if (subsystem_type != DRM_BUS_PCI)
+ return -ENODEV;
+
+ ret = drmProcessPciDevice(&d, node, node_type, maj, min, true, flags);
+ if (ret)
+ return ret;
+
+ *device = d;
+
+ return 0;
+#else
drmDevicePtr *local_devices;
drmDevicePtr d;
DIR *sysdir;
@@ -3098,6 +3774,9 @@ int drmGetDevice(int fd, drmDevicePtr *d
int max_count = 16;
dev_t find_rdev;
+ if (drm_device_validate_flags(flags))
+ return -EINVAL;
+
if (fd == -1 || device == NULL)
return -EINVAL;
@@ -3144,14 +3823,34 @@ int drmGetDevice(int fd, drmDevicePtr *d
switch (subsystem_type) {
case DRM_BUS_PCI:
- ret = drmProcessPciDevice(&d, dent->d_name, node, node_type,
- maj, min, true);
+ ret = drmProcessPciDevice(&d, node, node_type, maj, min, true, flags);
if (ret)
- goto free_devices;
+ continue;
+
+ break;
+
+ case DRM_BUS_USB:
+ ret = drmProcessUsbDevice(&d, node, node_type, maj, min, true, flags);
+ if (ret)
+ continue;
+
+ break;
+
+ case DRM_BUS_PLATFORM:
+ ret = drmProcessPlatformDevice(&d, node, node_type, maj, min, true, flags);
+ if (ret)
+ continue;
+
+ break;
+
+ case DRM_BUS_HOST1X:
+ ret = drmProcessHost1xDevice(&d, node, node_type, maj, min, true, flags);
+ if (ret)
+ continue;
break;
+
default:
- fprintf(stderr, "The subsystem type is not supported yet\n");
continue;
}
@@ -3183,6 +3882,8 @@ int drmGetDevice(int fd, drmDevicePtr *d
closedir(sysdir);
free(local_devices);
+ if (*device == NULL)
+ return -ENODEV;
return 0;
free_devices:
@@ -3192,11 +3893,27 @@ free_devices:
free_locals:
free(local_devices);
return ret;
+#endif
+}
+
+/**
+ * Get information about the opened drm device
+ *
+ * \param fd file descriptor of the drm device
+ * \param device the address of a drmDevicePtr where the information
+ * will be allocated in stored
+ *
+ * \return zero on success, negative error code otherwise.
+ */
+int drmGetDevice(int fd, drmDevicePtr *device)
+{
+ return drmGetDevice2(fd, DRM_DEVICE_GET_PCI_REVISION, device);
}
/**
* Get drm devices on the system
*
+ * \param flags feature/behaviour bitmask
* \param devices the array of devices with drmDevicePtr elements
* can be NULL to get the device number first
* \param max_devices the maximum number of devices for the array
@@ -3205,8 +3922,11 @@ free_locals:
* if devices is NULL - total number of devices available on the system,
* alternatively the number of devices stored in devices[], which is
* capped by the max_devices.
+ *
+ * \note Unlike drmGetDevices it does not retrieve the pci device revision field
+ * unless the DRM_DEVICE_GET_PCI_REVISION \p flag is set.
*/
-int drmGetDevices(drmDevicePtr devices[], int max_devices)
+int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices)
{
drmDevicePtr *local_devices;
drmDevicePtr device;
@@ -3219,6 +3939,9 @@ int drmGetDevices(drmDevicePtr devices[]
int ret, i, node_count, device_count;
int max_count = 16;
+ if (drm_device_validate_flags(flags))
+ return -EINVAL;
+
local_devices = calloc(max_count, sizeof(drmDevicePtr));
if (local_devices == NULL)
return -ENOMEM;
@@ -3252,14 +3975,38 @@ int drmGetDevices(drmDevicePtr devices[]
switch (subsystem_type) {
case DRM_BUS_PCI:
- ret = drmProcessPciDevice(&device, dent->d_name, node, node_type,
- maj, min, devices != NULL);
+ ret = drmProcessPciDevice(&device, node, node_type,
+ maj, min, devices != NULL, flags);
+ if (ret)
+ continue;
+
+ break;
+
+ case DRM_BUS_USB:
+ ret = drmProcessUsbDevice(&device, node, node_type, maj, min,
+ devices != NULL, flags);
if (ret)
goto free_devices;
break;
+
+ case DRM_BUS_PLATFORM:
+ ret = drmProcessPlatformDevice(&device, node, node_type, maj, min,
+ devices != NULL, flags);
+ if (ret)
+ goto free_devices;
+
+ break;
+
+ case DRM_BUS_HOST1X:
+ ret = drmProcessHost1xDevice(&device, node, node_type, maj, min,
+ devices != NULL, flags);
+ if (ret)
+ goto free_devices;
+
+ break;
+
default:
- fprintf(stderr, "The subsystem type is not supported yet\n");
continue;
}
@@ -3305,3 +4052,92 @@ free_locals:
free(local_devices);
return ret;
}
+
+/**
+ * Get drm devices on the system
+ *
+ * \param devices the array of devices with drmDevicePtr elements
+ * can be NULL to get the device number first
+ * \param max_devices the maximum number of devices for the array
+ *
+ * \return on error - negative error code,
+ * if devices is NULL - total number of devices available on the system,
+ * alternatively the number of devices stored in devices[], which is
+ * capped by the max_devices.
+ */
+int drmGetDevices(drmDevicePtr devices[], int max_devices)
+{
+ return drmGetDevices2(DRM_DEVICE_GET_PCI_REVISION, devices, max_devices);
+}
+
+char *drmGetDeviceNameFromFd2(int fd)
+{
+#ifdef __linux__
+ struct stat sbuf;
+ char path[PATH_MAX + 1], *value;
+ unsigned int maj, min;
+
+ if (fstat(fd, &sbuf))
+ return NULL;
+
+ maj = major(sbuf.st_rdev);
+ min = minor(sbuf.st_rdev);
+
+ if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+ return NULL;
+
+ snprintf(path, sizeof(path), "/sys/dev/char/%d:%d", maj, min);
+
+ value = sysfs_uevent_get(path, "DEVNAME");
+ if (!value)
+ return NULL;
+
+ snprintf(path, sizeof(path), "/dev/%s", value);
+ free(value);
+
+ return strdup(path);
+#else
+ struct stat sbuf;
+ char node[PATH_MAX + 1];
+ const char *dev_name;
+ int node_type;
+ int maj, min, n, base;
+
+ if (fstat(fd, &sbuf))
+ return NULL;
+
+ maj = major(sbuf.st_rdev);
+ min = minor(sbuf.st_rdev);
+
+ if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+ return NULL;
+
+ node_type = drmGetMinorType(min);
+ if (node_type == -1)
+ return NULL;
+
+ switch (node_type) {
+ case DRM_NODE_PRIMARY:
+ dev_name = DRM_DEV_NAME;
+ break;
+ case DRM_NODE_CONTROL:
+ dev_name = DRM_CONTROL_DEV_NAME;
+ break;
+ case DRM_NODE_RENDER:
+ dev_name = DRM_RENDER_DEV_NAME;
+ break;
+ default:
+ return NULL;
+ };
+
+ base = drmGetMinorBase(node_type);
+ if (base < 0)
+ return NULL;
+
+ n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min - base);
+ if (n == -1 || n >= PATH_MAX)
+ return NULL;
+
+ return strdup(node);
+#endif
+}
Index: xsrc/external/mit/libdrm/dist/xf86drm.h
diff -u xsrc/external/mit/libdrm/dist/xf86drm.h:1.6 xsrc/external/mit/libdrm/dist/xf86drm.h:1.7
--- xsrc/external/mit/libdrm/dist/xf86drm.h:1.6 Wed Aug 17 02:16:16 2016
+++ xsrc/external/mit/libdrm/dist/xf86drm.h Sat Mar 4 23:22:48 2017
@@ -762,6 +762,11 @@ typedef struct _drmEventContext {
extern int drmHandleEvent(int fd, drmEventContextPtr evctx);
extern char *drmGetDeviceNameFromFd(int fd);
+
+/* Improved version of drmGetDeviceNameFromFd which attributes for any type of
+ * device/node - card, control or renderD.
+ */
+extern char *drmGetDeviceNameFromFd2(int fd);
extern int drmGetNodeTypeFromFd(int fd);
extern int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd);
@@ -770,7 +775,10 @@ extern int drmPrimeFDToHandle(int fd, in
extern char *drmGetPrimaryDeviceNameFromFd(int fd);
extern char *drmGetRenderDeviceNameFromFd(int fd);
-#define DRM_BUS_PCI 0
+#define DRM_BUS_PCI 0
+#define DRM_BUS_USB 1
+#define DRM_BUS_PLATFORM 2
+#define DRM_BUS_HOST1X 3
typedef struct _drmPciBusInfo {
uint16_t domain;
@@ -787,15 +795,51 @@ typedef struct _drmPciDeviceInfo {
uint8_t revision_id;
} drmPciDeviceInfo, *drmPciDeviceInfoPtr;
+typedef struct _drmUsbBusInfo {
+ uint8_t bus;
+ uint8_t dev;
+} drmUsbBusInfo, *drmUsbBusInfoPtr;
+
+typedef struct _drmUsbDeviceInfo {
+ uint16_t vendor;
+ uint16_t product;
+} drmUsbDeviceInfo, *drmUsbDeviceInfoPtr;
+
+#define DRM_PLATFORM_DEVICE_NAME_LEN 512
+
+typedef struct _drmPlatformBusInfo {
+ char fullname[DRM_PLATFORM_DEVICE_NAME_LEN];
+} drmPlatformBusInfo, *drmPlatformBusInfoPtr;
+
+typedef struct _drmPlatformDeviceInfo {
+ char **compatible; /* NULL terminated list of compatible strings */
+} drmPlatformDeviceInfo, *drmPlatformDeviceInfoPtr;
+
+#define DRM_HOST1X_DEVICE_NAME_LEN 512
+
+typedef struct _drmHost1xBusInfo {
+ char fullname[DRM_HOST1X_DEVICE_NAME_LEN];
+} drmHost1xBusInfo, *drmHost1xBusInfoPtr;
+
+typedef struct _drmHost1xDeviceInfo {
+ char **compatible; /* NULL terminated list of compatible strings */
+} drmHost1xDeviceInfo, *drmHost1xDeviceInfoPtr;
+
typedef struct _drmDevice {
char **nodes; /* DRM_NODE_MAX sized array */
int available_nodes; /* DRM_NODE_* bitmask */
int bustype;
union {
drmPciBusInfoPtr pci;
+ drmUsbBusInfoPtr usb;
+ drmPlatformBusInfoPtr platform;
+ drmHost1xBusInfoPtr host1x;
} businfo;
union {
drmPciDeviceInfoPtr pci;
+ drmUsbDeviceInfoPtr usb;
+ drmPlatformDeviceInfoPtr platform;
+ drmHost1xDeviceInfoPtr host1x;
} deviceinfo;
} drmDevice, *drmDevicePtr;
@@ -805,6 +849,10 @@ extern void drmFreeDevice(drmDevicePtr *
extern int drmGetDevices(drmDevicePtr devices[], int max_devices);
extern void drmFreeDevices(drmDevicePtr devices[], int count);
+#define DRM_DEVICE_GET_PCI_REVISION (1 << 0)
+extern int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device);
+extern int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices);
+
#if defined(__cplusplus)
}
#endif
Index: xsrc/external/mit/libdrm/dist/xf86drmMode.h
diff -u xsrc/external/mit/libdrm/dist/xf86drmMode.h:1.6 xsrc/external/mit/libdrm/dist/xf86drmMode.h:1.7
--- xsrc/external/mit/libdrm/dist/xf86drmMode.h:1.6 Wed Aug 17 02:16:16 2016
+++ xsrc/external/mit/libdrm/dist/xf86drmMode.h Sat Mar 4 23:22:48 2017
@@ -123,13 +123,15 @@ extern "C" {
#define DRM_MODE_DITHERING_OFF 0
#define DRM_MODE_DITHERING_ON 1
-#define DRM_MODE_ENCODER_NONE 0
-#define DRM_MODE_ENCODER_DAC 1
-#define DRM_MODE_ENCODER_TMDS 2
-#define DRM_MODE_ENCODER_LVDS 3
-#define DRM_MODE_ENCODER_TVDAC 4
+#define DRM_MODE_ENCODER_NONE 0
+#define DRM_MODE_ENCODER_DAC 1
+#define DRM_MODE_ENCODER_TMDS 2
+#define DRM_MODE_ENCODER_LVDS 3
+#define DRM_MODE_ENCODER_TVDAC 4
#define DRM_MODE_ENCODER_VIRTUAL 5
-#define DRM_MODE_ENCODER_DSI 6
+#define DRM_MODE_ENCODER_DSI 6
+#define DRM_MODE_ENCODER_DPMST 7
+#define DRM_MODE_ENCODER_DPI 8
#define DRM_MODE_SUBCONNECTOR_Automatic 0
#define DRM_MODE_SUBCONNECTOR_Unknown 0
@@ -153,10 +155,11 @@ extern "C" {
#define DRM_MODE_CONNECTOR_DisplayPort 10
#define DRM_MODE_CONNECTOR_HDMIA 11
#define DRM_MODE_CONNECTOR_HDMIB 12
-#define DRM_MODE_CONNECTOR_TV 13
-#define DRM_MODE_CONNECTOR_eDP 14
+#define DRM_MODE_CONNECTOR_TV 13
+#define DRM_MODE_CONNECTOR_eDP 14
#define DRM_MODE_CONNECTOR_VIRTUAL 15
#define DRM_MODE_CONNECTOR_DSI 16
+#define DRM_MODE_CONNECTOR_DPI 17
#define DRM_MODE_PROP_PENDING (1<<0)
#define DRM_MODE_PROP_RANGE (1<<1)
@@ -369,6 +372,13 @@ extern int drmModeAddFB2(int fd, uint32_
uint32_t pixel_format, uint32_t bo_handles[4],
uint32_t pitches[4], uint32_t offsets[4],
uint32_t *buf_id, uint32_t flags);
+
+/* ...with format modifiers */
+int drmModeAddFB2WithModifiers(int fd, uint32_t width, uint32_t height,
+ uint32_t pixel_format, uint32_t bo_handles[4],
+ uint32_t pitches[4], uint32_t offsets[4],
+ uint64_t modifier[4], uint32_t *buf_id, uint32_t flags);
+
/**
* Destroies the given framebuffer.
*/
@@ -466,6 +476,9 @@ extern int drmModeCrtcGetGamma(int fd, u
uint16_t *red, uint16_t *green, uint16_t *blue);
extern int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id,
uint32_t flags, void *user_data);
+extern int drmModePageFlipTarget(int fd, uint32_t crtc_id, uint32_t fb_id,
+ uint32_t flags, void *user_data,
+ uint32_t target_vblank);
extern drmModePlaneResPtr drmModeGetPlaneResources(int fd);
extern drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id);
Index: xsrc/external/mit/libdrm/dist/xf86drmMode.c
diff -u xsrc/external/mit/libdrm/dist/xf86drmMode.c:1.10 xsrc/external/mit/libdrm/dist/xf86drmMode.c:1.11
--- xsrc/external/mit/libdrm/dist/xf86drmMode.c:1.10 Wed Aug 17 02:16:16 2016
+++ xsrc/external/mit/libdrm/dist/xf86drmMode.c Sat Mar 4 23:22:48 2017
@@ -270,10 +270,10 @@ int drmModeAddFB(int fd, uint32_t width,
return 0;
}
-int drmModeAddFB2(int fd, uint32_t width, uint32_t height,
- uint32_t pixel_format, uint32_t bo_handles[4],
- uint32_t pitches[4], uint32_t offsets[4],
- uint32_t *buf_id, uint32_t flags)
+int drmModeAddFB2WithModifiers(int fd, uint32_t width, uint32_t height,
+ uint32_t pixel_format, uint32_t bo_handles[4],
+ uint32_t pitches[4], uint32_t offsets[4],
+ uint64_t modifier[4], uint32_t *buf_id, uint32_t flags)
{
struct drm_mode_fb_cmd2 f;
int ret;
@@ -286,6 +286,8 @@ int drmModeAddFB2(int fd, uint32_t width
memcpy(f.handles, bo_handles, 4 * sizeof(bo_handles[0]));
memcpy(f.pitches, pitches, 4 * sizeof(pitches[0]));
memcpy(f.offsets, offsets, 4 * sizeof(offsets[0]));
+ if (modifier)
+ memcpy(f.modifier, modifier, 4 * sizeof(modifier[0]));
if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB2, &f)))
return ret;
@@ -294,6 +296,17 @@ int drmModeAddFB2(int fd, uint32_t width
return 0;
}
+int drmModeAddFB2(int fd, uint32_t width, uint32_t height,
+ uint32_t pixel_format, uint32_t bo_handles[4],
+ uint32_t pitches[4], uint32_t offsets[4],
+ uint32_t *buf_id, uint32_t flags)
+{
+ return drmModeAddFB2WithModifiers(fd, width, height,
+ pixel_format, bo_handles,
+ pitches, offsets, NULL,
+ buf_id, flags);
+}
+
int drmModeRmFB(int fd, uint32_t bufferId)
{
return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
@@ -901,7 +914,7 @@ int drmHandleEvent(int fd, drmEventConte
i = 0;
while (i < len) {
- e = (struct drm_event *) &buffer[i];
+ e = (struct drm_event *)(buffer + i);
switch (e->type) {
case DRM_EVENT_VBLANK:
if (evctx->version < 1 ||
@@ -948,6 +961,22 @@ int drmModePageFlip(int fd, uint32_t crt
return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip);
}
+int drmModePageFlipTarget(int fd, uint32_t crtc_id, uint32_t fb_id,
+ uint32_t flags, void *user_data,
+ uint32_t target_vblank)
+{
+ struct drm_mode_crtc_page_flip_target flip_target;
+
+ memclear(flip_target);
+ flip_target.fb_id = fb_id;
+ flip_target.crtc_id = crtc_id;
+ flip_target.user_data = VOID2U64(user_data);
+ flip_target.flags = flags;
+ flip_target.sequence = target_vblank;
+
+ return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip_target);
+}
+
int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id,
uint32_t fb_id, uint32_t flags,
uint32_t crtc_x, uint32_t crtc_y,
Index: xsrc/external/mit/libdrm/dist/include/drm/drm.h
diff -u xsrc/external/mit/libdrm/dist/include/drm/drm.h:1.6 xsrc/external/mit/libdrm/dist/include/drm/drm.h:1.7
--- xsrc/external/mit/libdrm/dist/include/drm/drm.h:1.6 Wed Aug 17 02:16:17 2016
+++ xsrc/external/mit/libdrm/dist/include/drm/drm.h Sat Mar 4 23:22:48 2017
@@ -59,6 +59,10 @@ typedef unsigned long drm_handle_t;
#endif
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */
#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */
#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */
@@ -636,6 +640,7 @@ struct drm_gem_open {
#define DRM_CAP_CURSOR_WIDTH 0x8
#define DRM_CAP_CURSOR_HEIGHT 0x9
#define DRM_CAP_ADDFB2_MODIFIERS 0x10
+#define DRM_CAP_PAGE_FLIP_TARGET 0x11
/** DRM_IOCTL_GET_CAP ioctl argument type */
struct drm_get_cap {
@@ -685,8 +690,16 @@ struct drm_prime_handle {
__s32 fd;
};
+#if defined(__cplusplus)
+}
+#endif
+
#include "drm_mode.h"
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#define DRM_IOCTL_BASE 'd'
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type)
@@ -878,4 +891,8 @@ typedef struct drm_agp_info drm_agp_info
typedef struct drm_scatter_gather drm_scatter_gather_t;
typedef struct drm_set_version drm_set_version_t;
+#if defined(__cplusplus)
+}
+#endif
+
#endif
Index: xsrc/external/mit/libdrm/dist/include/drm/i915_drm.h
diff -u xsrc/external/mit/libdrm/dist/include/drm/i915_drm.h:1.4 xsrc/external/mit/libdrm/dist/include/drm/i915_drm.h:1.5
--- xsrc/external/mit/libdrm/dist/include/drm/i915_drm.h:1.4 Wed Aug 17 02:16:17 2016
+++ xsrc/external/mit/libdrm/dist/include/drm/i915_drm.h Sat Mar 4 23:22:48 2017
@@ -29,6 +29,10 @@
#include "drm.h"
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
/* Please note that modifications to all structs defined here are
* subject to backwards-compatibility constraints.
*/
@@ -58,6 +62,30 @@
#define I915_ERROR_UEVENT "ERROR"
#define I915_RESET_UEVENT "RESET"
+/*
+ * MOCS indexes used for GPU surfaces, defining the cacheability of the
+ * surface data and the coherency for this data wrt. CPU vs. GPU accesses.
+ */
+enum i915_mocs_table_index {
+ /*
+ * Not cached anywhere, coherency between CPU and GPU accesses is
+ * guaranteed.
+ */
+ I915_MOCS_UNCACHED,
+ /*
+ * Cacheability and coherency controlled by the kernel automatically
+ * based on the DRM_I915_GEM_SET_CACHING IOCTL setting and the current
+ * usage of the surface (used for display scanout or not).
+ */
+ I915_MOCS_PTE,
+ /*
+ * Cached in all GPU caches available on the platform.
+ * Coherency between CPU and GPU accesses to the surface is not
+ * guaranteed without extra synchronization.
+ */
+ I915_MOCS_CACHED,
+};
+
/* Each region is a minimum of 16k, and there are at most 255 of them.
*/
#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use
@@ -218,6 +246,7 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_OVERLAY_PUT_IMAGE 0x27
#define DRM_I915_OVERLAY_ATTRS 0x28
#define DRM_I915_GEM_EXECBUFFER2 0x29
+#define DRM_I915_GEM_EXECBUFFER2_WR DRM_I915_GEM_EXECBUFFER2
#define DRM_I915_GET_SPRITE_COLORKEY 0x2a
#define DRM_I915_SET_SPRITE_COLORKEY 0x2b
#define DRM_I915_GEM_WAIT 0x2c
@@ -230,6 +259,7 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_GEM_USERPTR 0x33
#define DRM_I915_GEM_CONTEXT_GETPARAM 0x34
#define DRM_I915_GEM_CONTEXT_SETPARAM 0x35
+#define DRM_I915_PERF_OPEN 0x36
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -251,6 +281,7 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_GEM_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init)
#define DRM_IOCTL_I915_GEM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer)
#define DRM_IOCTL_I915_GEM_EXECBUFFER2 DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2, struct drm_i915_gem_execbuffer2)
+#define DRM_IOCTL_I915_GEM_EXECBUFFER2_WR DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2_WR, struct drm_i915_gem_execbuffer2)
#define DRM_IOCTL_I915_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin)
#define DRM_IOCTL_I915_GEM_UNPIN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin)
#define DRM_IOCTL_I915_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy)
@@ -283,6 +314,7 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_GEM_USERPTR DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_USERPTR, struct drm_i915_gem_userptr)
#define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param)
#define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param)
+#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
/* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware.
@@ -357,6 +389,28 @@ typedef struct drm_i915_irq_wait {
#define I915_PARAM_HAS_GPU_RESET 35
#define I915_PARAM_HAS_RESOURCE_STREAMER 36
#define I915_PARAM_HAS_EXEC_SOFTPIN 37
+#define I915_PARAM_HAS_POOLED_EU 38
+#define I915_PARAM_MIN_EU_IN_POOL 39
+#define I915_PARAM_MMAP_GTT_VERSION 40
+
+/* Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution
+ * priorities and the driver will attempt to execute batches in priority order.
+ */
+#define I915_PARAM_HAS_SCHEDULER 41
+#define I915_PARAM_HUC_STATUS 42
+
+/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to opt-out of
+ * synchronisation with implicit fencing on individual objects.
+ * See EXEC_OBJECT_ASYNC.
+ */
+#define I915_PARAM_HAS_EXEC_ASYNC 43
+
+/* Query whether DRM_I915_GEM_EXECBUFFER2 supports explicit fence support -
+ * both being able to pass in a sync_file fd to wait upon before executing,
+ * and being able to return a new sync_file fd that is signaled when the
+ * current request is complete. See I915_EXEC_FENCE_IN and I915_EXEC_FENCE_OUT.
+ */
+#define I915_PARAM_HAS_EXEC_FENCE 44
typedef struct drm_i915_getparam {
__s32 param;
@@ -692,15 +746,41 @@ struct drm_i915_gem_exec_object2 {
*/
__u64 offset;
-#define EXEC_OBJECT_NEEDS_FENCE (1<<0)
-#define EXEC_OBJECT_NEEDS_GTT (1<<1)
-#define EXEC_OBJECT_WRITE (1<<2)
+#define EXEC_OBJECT_NEEDS_FENCE (1<<0)
+#define EXEC_OBJECT_NEEDS_GTT (1<<1)
+#define EXEC_OBJECT_WRITE (1<<2)
#define EXEC_OBJECT_SUPPORTS_48B_ADDRESS (1<<3)
-#define EXEC_OBJECT_PINNED (1<<4)
-#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_PINNED<<1)
+#define EXEC_OBJECT_PINNED (1<<4)
+#define EXEC_OBJECT_PAD_TO_SIZE (1<<5)
+/* The kernel implicitly tracks GPU activity on all GEM objects, and
+ * synchronises operations with outstanding rendering. This includes
+ * rendering on other devices if exported via dma-buf. However, sometimes
+ * this tracking is too coarse and the user knows better. For example,
+ * if the object is split into non-overlapping ranges shared between different
+ * clients or engines (i.e. suballocating objects), the implicit tracking
+ * by kernel assumes that each operation affects the whole object rather
+ * than an individual range, causing needless synchronisation between clients.
+ * The kernel will also forgo any CPU cache flushes prior to rendering from
+ * the object as the client is expected to be also handling such domain
+ * tracking.
+ *
+ * The kernel maintains the implicit tracking in order to manage resources
+ * used by the GPU - this flag only disables the synchronisation prior to
+ * rendering with this object in this execbuf.
+ *
+ * Opting out of implicit synhronisation requires the user to do its own
+ * explicit tracking to avoid rendering corruption. See, for example,
+ * I915_PARAM_HAS_EXEC_FENCE to order execbufs and execute them asynchronously.
+ */
+#define EXEC_OBJECT_ASYNC (1<<6)
+/* All remaining bits are MBZ and RESERVED FOR FUTURE USE */
+#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_ASYNC<<1)
__u64 flags;
- __u64 rsvd1;
+ union {
+ __u64 rsvd1;
+ __u64 pad_to_size;
+ };
__u64 rsvd2;
};
@@ -784,7 +864,32 @@ struct drm_i915_gem_execbuffer2 {
*/
#define I915_EXEC_RESOURCE_STREAMER (1<<15)
-#define __I915_EXEC_UNKNOWN_FLAGS -(I915_EXEC_RESOURCE_STREAMER<<1)
+/* Setting I915_EXEC_FENCE_IN implies that lower_32_bits(rsvd2) represent
+ * a sync_file fd to wait upon (in a nonblocking manner) prior to executing
+ * the batch.
+ *
+ * Returns -EINVAL if the sync_file fd cannot be found.
+ */
+#define I915_EXEC_FENCE_IN (1<<16)
+
+/* Setting I915_EXEC_FENCE_OUT causes the ioctl to return a sync_file fd
+ * in the upper_32_bits(rsvd2) upon success. Ownership of the fd is given
+ * to the caller, and it should be close() after use. (The fd is a regular
+ * file descriptor and will be cleaned up on process termination. It holds
+ * a reference to the request, but nothing else.)
+ *
+ * The sync_file fd can be combined with other sync_file and passed either
+ * to execbuf using I915_EXEC_FENCE_IN, to atomic KMS ioctls (so that a flip
+ * will only occur after this request completes), or to other devices.
+ *
+ * Using I915_EXEC_FENCE_OUT requires use of
+ * DRM_IOCTL_I915_GEM_EXECBUFFER2_WR ioctl so that the result is written
+ * back to userspace. Failure to do so will cause the out-fence to always
+ * be reported as zero, and the real fence fd to be leaked.
+ */
+#define I915_EXEC_FENCE_OUT (1<<17)
+
+#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_OUT<<1))
#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff)
#define i915_execbuffer2_set_context_id(eb2, context) \
@@ -820,7 +925,16 @@ struct drm_i915_gem_busy {
* having flushed any pending activity), and a non-zero return that
* the object is still in-flight on the GPU. (The GPU has not yet
* signaled completion for all pending requests that reference the
- * object.)
+ * object.) An object is guaranteed to become idle eventually (so
+ * long as no new GPU commands are executed upon it). Due to the
+ * asynchronous nature of the hardware, an object reported
+ * as busy may become idle before the ioctl is completed.
+ *
+ * Furthermore, if the object is busy, which engine is busy is only
+ * provided as a guide. There are race conditions which prevent the
+ * report of which engines are busy from being always accurate.
+ * However, the converse is not true. If the object is idle, the
+ * result of the ioctl, that all engines are idle, is accurate.
*
* The returned dword is split into two fields to indicate both
* the engines on which the object is being read, and the
@@ -843,6 +957,11 @@ struct drm_i915_gem_busy {
* execution engines, e.g. multiple media engines, which are
* mapped to the same identifier in the EXECBUFFER2 ioctl and
* so are not separately reported for busyness.
+ *
+ * Caveat emptor:
+ * Only the boolean result of this query is reliable; that is whether
+ * the object is idle or busy. The report of which engines are busy
+ * should be only used as a heuristic.
*/
__u32 busy;
};
@@ -891,6 +1010,7 @@ struct drm_i915_gem_caching {
#define I915_TILING_NONE 0
#define I915_TILING_X 1
#define I915_TILING_Y 2
+#define I915_TILING_LAST I915_TILING_Y
#define I915_BIT_6_SWIZZLE_NONE 0
#define I915_BIT_6_SWIZZLE_9 1
@@ -1167,7 +1287,145 @@ struct drm_i915_gem_context_param {
#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1
#define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2
#define I915_CONTEXT_PARAM_GTT_SIZE 0x3
+#define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE 0x4
+#define I915_CONTEXT_PARAM_BANNABLE 0x5
__u64 value;
};
+enum drm_i915_oa_format {
+ I915_OA_FORMAT_A13 = 1,
+ I915_OA_FORMAT_A29,
+ I915_OA_FORMAT_A13_B8_C8,
+ I915_OA_FORMAT_B4_C8,
+ I915_OA_FORMAT_A45_B8_C8,
+ I915_OA_FORMAT_B4_C8_A16,
+ I915_OA_FORMAT_C4_B8,
+
+ I915_OA_FORMAT_MAX /* non-ABI */
+};
+
+enum drm_i915_perf_property_id {
+ /**
+ * Open the stream for a specific context handle (as used with
+ * execbuffer2). A stream opened for a specific context this way
+ * won't typically require root privileges.
+ */
+ DRM_I915_PERF_PROP_CTX_HANDLE = 1,
+
+ /**
+ * A value of 1 requests the inclusion of raw OA unit reports as
+ * part of stream samples.
+ */
+ DRM_I915_PERF_PROP_SAMPLE_OA,
+
+ /**
+ * The value specifies which set of OA unit metrics should be
+ * be configured, defining the contents of any OA unit reports.
+ */
+ DRM_I915_PERF_PROP_OA_METRICS_SET,
+
+ /**
+ * The value specifies the size and layout of OA unit reports.
+ */
+ DRM_I915_PERF_PROP_OA_FORMAT,
+
+ /**
+ * Specifying this property implicitly requests periodic OA unit
+ * sampling and (at least on Haswell) the sampling frequency is derived
+ * from this exponent as follows:
+ *
+ * 80ns * 2^(period_exponent + 1)
+ */
+ DRM_I915_PERF_PROP_OA_EXPONENT,
+
+ DRM_I915_PERF_PROP_MAX /* non-ABI */
+};
+
+struct drm_i915_perf_open_param {
+ __u32 flags;
+#define I915_PERF_FLAG_FD_CLOEXEC (1<<0)
+#define I915_PERF_FLAG_FD_NONBLOCK (1<<1)
+#define I915_PERF_FLAG_DISABLED (1<<2)
+
+ /** The number of u64 (id, value) pairs */
+ __u32 num_properties;
+
+ /**
+ * Pointer to array of u64 (id, value) pairs configuring the stream
+ * to open.
+ */
+ __u64 properties_ptr;
+};
+
+/**
+ * Enable data capture for a stream that was either opened in a disabled state
+ * via I915_PERF_FLAG_DISABLED or was later disabled via
+ * I915_PERF_IOCTL_DISABLE.
+ *
+ * It is intended to be cheaper to disable and enable a stream than it may be
+ * to close and re-open a stream with the same configuration.
+ *
+ * It's undefined whether any pending data for the stream will be lost.
+ */
+#define I915_PERF_IOCTL_ENABLE _IO('i', 0x0)
+
+/**
+ * Disable data capture for a stream.
+ *
+ * It is an error to try and read a stream that is disabled.
+ */
+#define I915_PERF_IOCTL_DISABLE _IO('i', 0x1)
+
+/**
+ * Common to all i915 perf records
+ */
+struct drm_i915_perf_record_header {
+ __u32 type;
+ __u16 pad;
+ __u16 size;
+};
+
+enum drm_i915_perf_record_type {
+
+ /**
+ * Samples are the work horse record type whose contents are extensible
+ * and defined when opening an i915 perf stream based on the given
+ * properties.
+ *
+ * Boolean properties following the naming convention
+ * DRM_I915_PERF_SAMPLE_xyz_PROP request the inclusion of 'xyz' data in
+ * every sample.
+ *
+ * The order of these sample properties given by userspace has no
+ * affect on the ordering of data within a sample. The order is
+ * documented here.
+ *
+ * struct {
+ * struct drm_i915_perf_record_header header;
+ *
+ * { u32 oa_report[]; } && DRM_I915_PERF_PROP_SAMPLE_OA
+ * };
+ */
+ DRM_I915_PERF_RECORD_SAMPLE = 1,
+
+ /*
+ * Indicates that one or more OA reports were not written by the
+ * hardware. This can happen for example if an MI_REPORT_PERF_COUNT
+ * command collides with periodic sampling - which would be more likely
+ * at higher sampling frequencies.
+ */
+ DRM_I915_PERF_RECORD_OA_REPORT_LOST = 2,
+
+ /**
+ * An error occurred that resulted in all pending OA reports being lost.
+ */
+ DRM_I915_PERF_RECORD_OA_BUFFER_LOST = 3,
+
+ DRM_I915_PERF_RECORD_MAX /* non-ABI */
+};
+
+#if defined(__cplusplus)
+}
+#endif
+
#endif /* _I915_DRM_H_ */
Index: xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c
diff -u xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c:1.12 xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c:1.13
--- xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c:1.12 Wed Aug 17 02:16:17 2016
+++ xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c Sat Mar 4 23:22:48 2017
@@ -65,6 +65,7 @@
#include "string.h"
#include "i915_drm.h"
+#include "uthash.h"
#ifdef HAVE_VALGRIND
#include <valgrind.h>
@@ -131,7 +132,9 @@ typedef struct _drm_intel_bufmgr_gem {
drmMMListHead managers;
- drmMMListHead named;
+ drm_intel_bo_gem *name_table;
+ drm_intel_bo_gem *handle_table;
+
drmMMListHead vma_cache;
int vma_count, vma_open, vma_max;
@@ -147,6 +150,7 @@ typedef struct _drm_intel_bufmgr_gem {
unsigned int bo_reuse : 1;
unsigned int no_exec : 1;
unsigned int has_vebox : 1;
+ unsigned int has_exec_async : 1;
bool fenced_relocs;
struct {
@@ -176,7 +180,9 @@ struct _drm_intel_bo_gem {
* List contains both flink named and prime fd'd objects
*/
unsigned int global_name;
- drmMMListHead name_list;
+
+ UT_hash_handle handle_hh;
+ UT_hash_handle name_hh;
/**
* Index of the buffer within the validation list while preparing a
@@ -191,6 +197,8 @@ struct _drm_intel_bo_gem {
uint32_t swizzle_mode;
unsigned long stride;
+ unsigned long kflags;
+
time_t free_time;
/** Array passed to the DRM containing relocation information. */
@@ -212,6 +220,8 @@ struct _drm_intel_bo_gem {
void *mem_virtual;
/** GTT virtual address for the buffer, saved across map/unmap cycles */
void *gtt_virtual;
+ /** WC CPU address for the buffer, saved across map/unmap cycles */
+ void *wc_virtual;
/**
* Virtual address of the buffer allocated by user, used for userptr
* objects only.
@@ -250,7 +260,7 @@ struct _drm_intel_bo_gem {
* Boolean of whether the GPU is definitely not accessing the buffer.
*
* This is only valid when reusable, since non-reusable
- * buffers are those that have been shared wth other
+ * buffers are those that have been shared with other
* processes, so we don't know their state.
*/
bool idle;
@@ -288,7 +298,7 @@ struct _drm_intel_bo_gem {
*/
int reloc_tree_fences;
- /** Flags that we may need to do the SW_FINSIH ioctl on unmap. */
+ /** Flags that we may need to do the SW_FINISH ioctl on unmap. */
bool mapped_cpu_write;
};
@@ -569,12 +579,11 @@ drm_intel_add_validate_buffer2(drm_intel
bufmgr_gem->exec2_objects[index].relocation_count = bo_gem->reloc_count;
bufmgr_gem->exec2_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs;
bufmgr_gem->exec2_objects[index].alignment = bo->align;
- bufmgr_gem->exec2_objects[index].offset = bo_gem->is_softpin ?
- bo->offset64 : 0;
- bufmgr_gem->exec_bos[index] = bo;
- bufmgr_gem->exec2_objects[index].flags = flags;
+ bufmgr_gem->exec2_objects[index].offset = bo->offset64;
+ bufmgr_gem->exec2_objects[index].flags = flags | bo_gem->kflags;
bufmgr_gem->exec2_objects[index].rsvd1 = 0;
bufmgr_gem->exec2_objects[index].rsvd2 = 0;
+ bufmgr_gem->exec_bos[index] = bo;
bufmgr_gem->exec_count++;
}
@@ -798,14 +807,17 @@ retry:
}
}
}
- pthread_mutex_unlock(&bufmgr_gem->lock);
if (!alloc_from_cache) {
struct drm_i915_gem_create create;
bo_gem = calloc(1, sizeof(*bo_gem));
if (!bo_gem)
- return NULL;
+ goto err;
+
+ /* drm_intel_gem_bo_free calls DRMLISTDEL() for an uninitialized
+ list (vma_list), so better set the list head here */
+ DRMINITLISTHEAD(&bo_gem->vma_list);
bo_gem->bo.size = bo_size;
@@ -815,12 +827,13 @@ retry:
ret = drmIoctl(bufmgr_gem->fd,
DRM_IOCTL_I915_GEM_CREATE,
&create);
- bo_gem->gem_handle = create.handle;
- bo_gem->bo.handle = bo_gem->gem_handle;
if (ret != 0) {
free(bo_gem);
- return NULL;
+ goto err;
}
+
+ bo_gem->gem_handle = create.handle;
+ bo_gem->bo.handle = bo_gem->gem_handle;
bo_gem->bo.bufmgr = bufmgr;
bo_gem->bo.align = alignment;
@@ -828,16 +841,14 @@ retry:
bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
bo_gem->stride = 0;
- /* drm_intel_gem_bo_free calls DRMLISTDEL() for an uninitialized
- list (vma_list), so better set the list head here */
- DRMINITLISTHEAD(&bo_gem->name_list);
- DRMINITLISTHEAD(&bo_gem->vma_list);
if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo,
tiling_mode,
- stride)) {
- drm_intel_gem_bo_free(&bo_gem->bo);
- return NULL;
- }
+ stride))
+ goto err_free;
+
+ HASH_ADD(handle_hh, bufmgr_gem->handle_table,
+ gem_handle, sizeof(bo_gem->gem_handle),
+ bo_gem);
}
bo_gem->name = name;
@@ -850,11 +861,18 @@ retry:
bo_gem->use_48b_address_range = false;
drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, alignment);
+ pthread_mutex_unlock(&bufmgr_gem->lock);
DBG("bo_create: buf %d (%s) %ldb\n",
bo_gem->gem_handle, bo_gem->name, size);
return &bo_gem->bo;
+
+err_free:
+ drm_intel_gem_bo_free(&bo_gem->bo);
+err:
+ pthread_mutex_unlock(&bufmgr_gem->lock);
+ return NULL;
}
static drm_intel_bo *
@@ -955,6 +973,9 @@ drm_intel_gem_bo_alloc_userptr(drm_intel
if (!bo_gem)
return NULL;
+ atomic_set(&bo_gem->refcount, 1);
+ DRMINITLISTHEAD(&bo_gem->vma_list);
+
bo_gem->bo.size = size;
memclear(userptr);
@@ -973,6 +994,8 @@ drm_intel_gem_bo_alloc_userptr(drm_intel
return NULL;
}
+ pthread_mutex_lock(&bufmgr_gem->lock);
+
bo_gem->gem_handle = userptr.handle;
bo_gem->bo.handle = bo_gem->gem_handle;
bo_gem->bo.bufmgr = bufmgr;
@@ -984,11 +1007,11 @@ drm_intel_gem_bo_alloc_userptr(drm_intel
bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
bo_gem->stride = 0;
- DRMINITLISTHEAD(&bo_gem->name_list);
- DRMINITLISTHEAD(&bo_gem->vma_list);
+ HASH_ADD(handle_hh, bufmgr_gem->handle_table,
+ gem_handle, sizeof(bo_gem->gem_handle),
+ bo_gem);
bo_gem->name = name;
- atomic_set(&bo_gem->refcount, 1);
bo_gem->validate_index = -1;
bo_gem->reloc_tree_fences = 0;
bo_gem->used_as_reloc_target = false;
@@ -997,6 +1020,7 @@ drm_intel_gem_bo_alloc_userptr(drm_intel
bo_gem->use_48b_address_range = false;
drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
+ pthread_mutex_unlock(&bufmgr_gem->lock);
DBG("bo_create_userptr: "
"ptr %p buf %d (%s) size %ldb, stride 0x%x, tile mode %d\n",
@@ -1086,7 +1110,6 @@ drm_intel_bo_gem_create_from_name(drm_in
int ret;
struct drm_gem_open open_arg;
struct drm_i915_gem_get_tiling get_tiling;
- drmMMListHead *list;
/* At the moment most applications only have a few named bo.
* For instance, in a DRI client only the render buffers passed
@@ -1095,15 +1118,11 @@ drm_intel_bo_gem_create_from_name(drm_in
* provides a sufficiently fast match.
*/
pthread_mutex_lock(&bufmgr_gem->lock);
- for (list = bufmgr_gem->named.next;
- list != &bufmgr_gem->named;
- list = list->next) {
- bo_gem = DRMLISTENTRY(drm_intel_bo_gem, list, name_list);
- if (bo_gem->global_name == handle) {
- drm_intel_gem_bo_reference(&bo_gem->bo);
- pthread_mutex_unlock(&bufmgr_gem->lock);
- return &bo_gem->bo;
- }
+ HASH_FIND(name_hh, bufmgr_gem->name_table,
+ &handle, sizeof(handle), bo_gem);
+ if (bo_gem) {
+ drm_intel_gem_bo_reference(&bo_gem->bo);
+ goto out;
}
memclear(open_arg);
@@ -1114,29 +1133,26 @@ drm_intel_bo_gem_create_from_name(drm_in
if (ret != 0) {
DBG("Couldn't reference %s handle 0x%08x: %s\n",
name, handle, strerror(errno));
- pthread_mutex_unlock(&bufmgr_gem->lock);
- return NULL;
+ bo_gem = NULL;
+ goto out;
}
/* Now see if someone has used a prime handle to get this
* object from the kernel before by looking through the list
* again for a matching gem_handle
*/
- for (list = bufmgr_gem->named.next;
- list != &bufmgr_gem->named;
- list = list->next) {
- bo_gem = DRMLISTENTRY(drm_intel_bo_gem, list, name_list);
- if (bo_gem->gem_handle == open_arg.handle) {
- drm_intel_gem_bo_reference(&bo_gem->bo);
- pthread_mutex_unlock(&bufmgr_gem->lock);
- return &bo_gem->bo;
- }
+ HASH_FIND(handle_hh, bufmgr_gem->handle_table,
+ &open_arg.handle, sizeof(open_arg.handle), bo_gem);
+ if (bo_gem) {
+ drm_intel_gem_bo_reference(&bo_gem->bo);
+ goto out;
}
bo_gem = calloc(1, sizeof(*bo_gem));
- if (!bo_gem) {
- pthread_mutex_unlock(&bufmgr_gem->lock);
- return NULL;
- }
+ if (!bo_gem)
+ goto out;
+
+ atomic_set(&bo_gem->refcount, 1);
+ DRMINITLISTHEAD(&bo_gem->vma_list);
bo_gem->bo.size = open_arg.size;
bo_gem->bo.offset = 0;
@@ -1144,7 +1160,6 @@ drm_intel_bo_gem_create_from_name(drm_in
bo_gem->bo.virtual = NULL;
bo_gem->bo.bufmgr = bufmgr;
bo_gem->name = name;
- atomic_set(&bo_gem->refcount, 1);
bo_gem->validate_index = -1;
bo_gem->gem_handle = open_arg.handle;
bo_gem->bo.handle = open_arg.handle;
@@ -1152,27 +1167,33 @@ drm_intel_bo_gem_create_from_name(drm_in
bo_gem->reusable = false;
bo_gem->use_48b_address_range = false;
+ HASH_ADD(handle_hh, bufmgr_gem->handle_table,
+ gem_handle, sizeof(bo_gem->gem_handle), bo_gem);
+ HASH_ADD(name_hh, bufmgr_gem->name_table,
+ global_name, sizeof(bo_gem->global_name), bo_gem);
+
memclear(get_tiling);
get_tiling.handle = bo_gem->gem_handle;
ret = drmIoctl(bufmgr_gem->fd,
DRM_IOCTL_I915_GEM_GET_TILING,
&get_tiling);
- if (ret != 0) {
- drm_intel_gem_bo_unreference(&bo_gem->bo);
- pthread_mutex_unlock(&bufmgr_gem->lock);
- return NULL;
- }
+ if (ret != 0)
+ goto err_unref;
+
bo_gem->tiling_mode = get_tiling.tiling_mode;
bo_gem->swizzle_mode = get_tiling.swizzle_mode;
/* XXX stride is unknown */
drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
-
- DRMINITLISTHEAD(&bo_gem->vma_list);
- DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named);
- pthread_mutex_unlock(&bufmgr_gem->lock);
DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name);
+out:
+ pthread_mutex_unlock(&bufmgr_gem->lock);
return &bo_gem->bo;
+
+err_unref:
+ drm_intel_gem_bo_free(&bo_gem->bo);
+ pthread_mutex_unlock(&bufmgr_gem->lock);
+ return NULL;
}
static void
@@ -1189,11 +1210,20 @@ drm_intel_gem_bo_free(drm_intel_bo *bo)
drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size);
bufmgr_gem->vma_count--;
}
+ if (bo_gem->wc_virtual) {
+ VG(VALGRIND_FREELIKE_BLOCK(bo_gem->wc_virtual, 0));
+ drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size);
+ bufmgr_gem->vma_count--;
+ }
if (bo_gem->gtt_virtual) {
drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
bufmgr_gem->vma_count--;
}
+ if (bo_gem->global_name)
+ HASH_DELETE(name_hh, bufmgr_gem->name_table, bo_gem);
+ HASH_DELETE(handle_hh, bufmgr_gem->handle_table, bo_gem);
+
/* Close this object */
memclear(close);
close.handle = bo_gem->gem_handle;
@@ -1214,6 +1244,9 @@ drm_intel_gem_bo_mark_mmaps_incoherent(d
if (bo_gem->mem_virtual)
VALGRIND_MAKE_MEM_NOACCESS(bo_gem->mem_virtual, bo->size);
+ if (bo_gem->wc_virtual)
+ VALGRIND_MAKE_MEM_NOACCESS(bo_gem->wc_virtual, bo->size);
+
if (bo_gem->gtt_virtual)
VALGRIND_MAKE_MEM_NOACCESS(bo_gem->gtt_virtual, bo->size);
#endif
@@ -1278,6 +1311,11 @@ static void drm_intel_gem_bo_purge_vma_c
bo_gem->mem_virtual = NULL;
bufmgr_gem->vma_count--;
}
+ if (bo_gem->wc_virtual) {
+ drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size);
+ bo_gem->wc_virtual = NULL;
+ bufmgr_gem->vma_count--;
+ }
if (bo_gem->gtt_virtual) {
drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
bo_gem->gtt_virtual = NULL;
@@ -1293,6 +1331,8 @@ static void drm_intel_gem_bo_close_vma(d
DRMLISTADDTAIL(&bo_gem->vma_list, &bufmgr_gem->vma_cache);
if (bo_gem->mem_virtual)
bufmgr_gem->vma_count++;
+ if (bo_gem->wc_virtual)
+ bufmgr_gem->vma_count++;
if (bo_gem->gtt_virtual)
bufmgr_gem->vma_count++;
drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
@@ -1305,6 +1345,8 @@ static void drm_intel_gem_bo_open_vma(dr
DRMLISTDEL(&bo_gem->vma_list);
if (bo_gem->mem_virtual)
bufmgr_gem->vma_count--;
+ if (bo_gem->wc_virtual)
+ bufmgr_gem->vma_count--;
if (bo_gem->gtt_virtual)
bufmgr_gem->vma_count--;
drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
@@ -1329,6 +1371,7 @@ drm_intel_gem_bo_unreference_final(drm_i
for (i = 0; i < bo_gem->softpin_target_count; i++)
drm_intel_gem_bo_unreference_locked_timed(bo_gem->softpin_target[i],
time);
+ bo_gem->kflags = 0;
bo_gem->reloc_count = 0;
bo_gem->used_as_reloc_target = false;
bo_gem->softpin_target_count = 0;
@@ -1359,8 +1402,6 @@ drm_intel_gem_bo_unreference_final(drm_i
drm_intel_gem_bo_mark_mmaps_incoherent(bo);
}
- DRMLISTDEL(&bo_gem->name_list);
-
bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo->size);
/* Put the buffer into our internal cache for reuse if we can. */
if (bufmgr_gem->bo_reuse && bo_gem->reusable && bucket != NULL &&
@@ -1371,6 +1412,8 @@ drm_intel_gem_bo_unreference_final(drm_i
bo_gem->name = NULL;
bo_gem->validate_index = -1;
+ bo_gem->kflags = 0;
+
DRMLISTADDTAIL(&bo_gem->head, &bucket->head);
} else {
drm_intel_gem_bo_free(bo);
@@ -1680,7 +1723,7 @@ static int drm_intel_gem_bo_unmap(drm_in
}
/* We need to unmap after every innovation as we cannot track
- * an open vma for every bo as that will exhaasut the system
+ * an open vma for every bo as that will exhaust the system
* limits and cause later failures.
*/
if (--bo_gem->map_count == 0) {
@@ -2334,6 +2377,7 @@ drm_intel_gem_bo_exec(drm_intel_bo *bo,
static int
do_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx,
drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
+ int in_fence, int *out_fence,
unsigned int flags)
{
drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
@@ -2388,12 +2432,20 @@ do_exec2(drm_intel_bo *bo, int used, drm
else
i915_execbuffer2_set_context_id(execbuf, ctx->ctx_id);
execbuf.rsvd2 = 0;
+ if (in_fence != -1) {
+ execbuf.rsvd2 = in_fence;
+ execbuf.flags |= I915_EXEC_FENCE_IN;
+ }
+ if (out_fence != NULL) {
+ *out_fence = -1;
+ execbuf.flags |= I915_EXEC_FENCE_OUT;
+ }
if (bufmgr_gem->no_exec)
goto skip_execution;
ret = drmIoctl(bufmgr_gem->fd,
- DRM_IOCTL_I915_GEM_EXECBUFFER2,
+ DRM_IOCTL_I915_GEM_EXECBUFFER2_WR,
&execbuf);
if (ret != 0) {
ret = -errno;
@@ -2409,6 +2461,9 @@ do_exec2(drm_intel_bo *bo, int used, drm
}
drm_intel_update_buffer_offsets2(bufmgr_gem);
+ if (ret == 0 && out_fence != NULL)
+ *out_fence = execbuf.rsvd2 >> 32;
+
skip_execution:
if (bufmgr_gem->bufmgr.debug)
drm_intel_gem_dump_validation_list(bufmgr_gem);
@@ -2434,7 +2489,7 @@ drm_intel_gem_bo_exec2(drm_intel_bo *bo,
int DR4)
{
return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
- I915_EXEC_RENDER);
+ -1, NULL, I915_EXEC_RENDER);
}
static int
@@ -2443,14 +2498,25 @@ drm_intel_gem_bo_mrb_exec2(drm_intel_bo
unsigned int flags)
{
return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
- flags);
+ -1, NULL, flags);
}
int
drm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx,
int used, unsigned int flags)
{
- return do_exec2(bo, used, ctx, NULL, 0, 0, flags);
+ return do_exec2(bo, used, ctx, NULL, 0, 0, -1, NULL, flags);
+}
+
+int
+drm_intel_gem_bo_fence_exec(drm_intel_bo *bo,
+ drm_intel_context *ctx,
+ int used,
+ int in_fence,
+ int *out_fence,
+ unsigned int flags)
+{
+ return do_exec2(bo, used, ctx, NULL, 0, 0, in_fence, out_fence, flags);
}
static int
@@ -2590,7 +2656,6 @@ drm_intel_bo_gem_create_from_prime(drm_i
uint32_t handle;
drm_intel_bo_gem *bo_gem;
struct drm_i915_gem_get_tiling get_tiling;
- drmMMListHead *list;
pthread_mutex_lock(&bufmgr_gem->lock);
ret = drmPrimeFDToHandle(bufmgr_gem->fd, prime_fd, &handle);
@@ -2605,22 +2670,20 @@ drm_intel_bo_gem_create_from_prime(drm_i
* for named buffers, we must not create two bo's pointing at the same
* kernel object
*/
- for (list = bufmgr_gem->named.next;
- list != &bufmgr_gem->named;
- list = list->next) {
- bo_gem = DRMLISTENTRY(drm_intel_bo_gem, list, name_list);
- if (bo_gem->gem_handle == handle) {
- drm_intel_gem_bo_reference(&bo_gem->bo);
- pthread_mutex_unlock(&bufmgr_gem->lock);
- return &bo_gem->bo;
- }
+ HASH_FIND(handle_hh, bufmgr_gem->handle_table,
+ &handle, sizeof(handle), bo_gem);
+ if (bo_gem) {
+ drm_intel_gem_bo_reference(&bo_gem->bo);
+ goto out;
}
bo_gem = calloc(1, sizeof(*bo_gem));
- if (!bo_gem) {
- pthread_mutex_unlock(&bufmgr_gem->lock);
- return NULL;
- }
+ if (!bo_gem)
+ goto out;
+
+ atomic_set(&bo_gem->refcount, 1);
+ DRMINITLISTHEAD(&bo_gem->vma_list);
+
/* Determine size of bo. The fd-to-handle ioctl really should
* return the size, but it doesn't. If we have kernel 3.12 or
* later, we can lseek on the prime fd to get the size. Older
@@ -2636,8 +2699,8 @@ drm_intel_bo_gem_create_from_prime(drm_i
bo_gem->bo.bufmgr = bufmgr;
bo_gem->gem_handle = handle;
-
- atomic_set(&bo_gem->refcount, 1);
+ HASH_ADD(handle_hh, bufmgr_gem->handle_table,
+ gem_handle, sizeof(bo_gem->gem_handle), bo_gem);
bo_gem->name = "prime";
bo_gem->validate_index = -1;
@@ -2647,26 +2710,26 @@ drm_intel_bo_gem_create_from_prime(drm_i
bo_gem->reusable = false;
bo_gem->use_48b_address_range = false;
- DRMINITLISTHEAD(&bo_gem->vma_list);
- DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named);
- pthread_mutex_unlock(&bufmgr_gem->lock);
-
memclear(get_tiling);
get_tiling.handle = bo_gem->gem_handle;
- ret = drmIoctl(bufmgr_gem->fd,
- DRM_IOCTL_I915_GEM_GET_TILING,
- &get_tiling);
- if (ret != 0) {
- DBG("create_from_prime: failed to get tiling: %s\n", strerror(errno));
- drm_intel_gem_bo_unreference(&bo_gem->bo);
- return NULL;
- }
+ if (drmIoctl(bufmgr_gem->fd,
+ DRM_IOCTL_I915_GEM_GET_TILING,
+ &get_tiling))
+ goto err;
+
bo_gem->tiling_mode = get_tiling.tiling_mode;
bo_gem->swizzle_mode = get_tiling.swizzle_mode;
/* XXX stride is unknown */
drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
+out:
+ pthread_mutex_unlock(&bufmgr_gem->lock);
return &bo_gem->bo;
+
+err:
+ drm_intel_gem_bo_free(&bo_gem->bo);
+ pthread_mutex_unlock(&bufmgr_gem->lock);
+ return NULL;
}
int
@@ -2675,11 +2738,6 @@ drm_intel_bo_gem_export_to_prime(drm_int
drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
- pthread_mutex_lock(&bufmgr_gem->lock);
- if (DRMLISTEMPTY(&bo_gem->name_list))
- DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named);
- pthread_mutex_unlock(&bufmgr_gem->lock);
-
if (drmPrimeHandleToFD(bufmgr_gem->fd, bo_gem->gem_handle,
DRM_CLOEXEC, prime_fd) != 0)
return -errno;
@@ -2694,27 +2752,24 @@ drm_intel_gem_bo_flink(drm_intel_bo *bo,
{
drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
- int ret;
if (!bo_gem->global_name) {
struct drm_gem_flink flink;
memclear(flink);
flink.handle = bo_gem->gem_handle;
+ if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink))
+ return -errno;
pthread_mutex_lock(&bufmgr_gem->lock);
-
- ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink);
- if (ret != 0) {
- pthread_mutex_unlock(&bufmgr_gem->lock);
- return -errno;
+ if (!bo_gem->global_name) {
+ bo_gem->global_name = flink.name;
+ bo_gem->reusable = false;
+
+ HASH_ADD(name_hh, bufmgr_gem->name_table,
+ global_name, sizeof(bo_gem->global_name),
+ bo_gem);
}
-
- bo_gem->global_name = flink.name;
- bo_gem->reusable = false;
-
- if (DRMLISTEMPTY(&bo_gem->name_list))
- DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named);
pthread_mutex_unlock(&bufmgr_gem->lock);
}
@@ -2738,6 +2793,59 @@ drm_intel_bufmgr_gem_enable_reuse(drm_in
}
/**
+ * Disables implicit synchronisation before executing the bo
+ *
+ * This will cause rendering corruption unless you correctly manage explicit
+ * fences for all rendering involving this buffer - including use by others.
+ * Disabling the implicit serialisation is only required if that serialisation
+ * is too coarse (for example, you have split the buffer into many
+ * non-overlapping regions and are sharing the whole buffer between concurrent
+ * independent command streams).
+ *
+ * Note the kernel must advertise support via I915_PARAM_HAS_EXEC_ASYNC,
+ * which can be checked using drm_intel_bufmgr_can_disable_implicit_sync,
+ * or subsequent execbufs involving the bo will generate EINVAL.
+ */
+void
+drm_intel_gem_bo_disable_implicit_sync(drm_intel_bo *bo)
+{
+ drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+
+ bo_gem->kflags |= EXEC_OBJECT_ASYNC;
+}
+
+/**
+ * Enables implicit synchronisation before executing the bo
+ *
+ * This is the default behaviour of the kernel, to wait upon prior writes
+ * completing on the object before rendering with it, or to wait for prior
+ * reads to complete before writing into the object.
+ * drm_intel_gem_bo_disable_implicit_sync() can stop this behaviour, telling
+ * the kernel never to insert a stall before using the object. Then this
+ * function can be used to restore the implicit sync before subsequent
+ * rendering.
+ */
+void
+drm_intel_gem_bo_enable_implicit_sync(drm_intel_bo *bo)
+{
+ drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+
+ bo_gem->kflags &= ~EXEC_OBJECT_ASYNC;
+}
+
+/**
+ * Query whether the kernel supports disabling of its implicit synchronisation
+ * before execbuf. See drm_intel_gem_bo_disable_implicit_sync()
+ */
+int
+drm_intel_bufmgr_gem_can_disable_implicit_sync(drm_intel_bufmgr *bufmgr)
+{
+ drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
+
+ return bufmgr_gem->has_exec_async;
+}
+
+/**
* Enable use of fenced reloc type.
*
* New code should enable this to avoid unnecessary fence register
@@ -3033,6 +3141,34 @@ drm_intel_bufmgr_gem_set_vma_cache_size(
drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
}
+static int
+parse_devid_override(const char *devid_override)
+{
+ static const struct {
+ const char *name;
+ int pci_id;
+ } name_map[] = {
+ { "brw", PCI_CHIP_I965_GM },
+ { "g4x", PCI_CHIP_GM45_GM },
+ { "ilk", PCI_CHIP_ILD_G },
+ { "snb", PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS },
+ { "ivb", PCI_CHIP_IVYBRIDGE_S_GT2 },
+ { "hsw", PCI_CHIP_HASWELL_CRW_E_GT3 },
+ { "byt", PCI_CHIP_VALLEYVIEW_3 },
+ { "bdw", 0x1620 | BDW_ULX },
+ { "skl", PCI_CHIP_SKYLAKE_DT_GT2 },
+ { "kbl", PCI_CHIP_KABYLAKE_DT_GT2 },
+ };
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(name_map); i++) {
+ if (!strcmp(name_map[i].name, devid_override))
+ return name_map[i].pci_id;
+ }
+
+ return strtod(devid_override, NULL);
+}
+
/**
* Get the PCI ID for the device. This can be overridden by setting the
* INTEL_DEVID_OVERRIDE environment variable to the desired ID.
@@ -3049,7 +3185,7 @@ get_pci_device_id(drm_intel_bufmgr_gem *
devid_override = getenv("INTEL_DEVID_OVERRIDE");
if (devid_override) {
bufmgr_gem->no_exec = true;
- return strtod(devid_override, NULL);
+ return parse_devid_override(devid_override);
}
}
@@ -3129,6 +3265,17 @@ drm_intel_gem_context_create(drm_intel_b
return context;
}
+int
+drm_intel_gem_context_get_id(drm_intel_context *ctx, uint32_t *ctx_id)
+{
+ if (ctx == NULL)
+ return -EINVAL;
+
+ *ctx_id = ctx->ctx_id;
+
+ return 0;
+}
+
void
drm_intel_gem_context_destroy(drm_intel_context *ctx)
{
@@ -3236,6 +3383,36 @@ drm_intel_get_eu_total(int fd, unsigned
return 0;
}
+int
+drm_intel_get_pooled_eu(int fd)
+{
+ drm_i915_getparam_t gp;
+ int ret = -1;
+
+ memclear(gp);
+ gp.param = I915_PARAM_HAS_POOLED_EU;
+ gp.value = &ret;
+ if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp))
+ return -errno;
+
+ return ret;
+}
+
+int
+drm_intel_get_min_eu_in_pool(int fd)
+{
+ drm_i915_getparam_t gp;
+ int ret = -1;
+
+ memclear(gp);
+ gp.param = I915_PARAM_MIN_EU_IN_POOL;
+ gp.value = &ret;
+ if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp))
+ return -errno;
+
+ return ret;
+}
+
/**
* Annotate the given bo for use in aub dumping.
*
@@ -3299,6 +3476,141 @@ drm_intel_bufmgr_gem_unref(drm_intel_buf
}
}
+void *drm_intel_gem_bo_map__gtt(drm_intel_bo *bo)
+{
+ drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+ drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+
+ if (bo_gem->gtt_virtual)
+ return bo_gem->gtt_virtual;
+
+ if (bo_gem->is_userptr)
+ return NULL;
+
+ pthread_mutex_lock(&bufmgr_gem->lock);
+ if (bo_gem->gtt_virtual == NULL) {
+ struct drm_i915_gem_mmap_gtt mmap_arg;
+ void *ptr;
+
+ DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n",
+ bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
+
+ if (bo_gem->map_count++ == 0)
+ drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
+
+ memclear(mmap_arg);
+ mmap_arg.handle = bo_gem->gem_handle;
+
+ /* Get the fake offset back... */
+ ptr = MAP_FAILED;
+ if (drmIoctl(bufmgr_gem->fd,
+ DRM_IOCTL_I915_GEM_MMAP_GTT,
+ &mmap_arg) == 0) {
+ /* and mmap it */
+ ptr = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, bufmgr_gem->fd,
+ mmap_arg.offset);
+ }
+ if (ptr == MAP_FAILED) {
+ if (--bo_gem->map_count == 0)
+ drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
+ ptr = NULL;
+ }
+
+ bo_gem->gtt_virtual = ptr;
+ }
+ pthread_mutex_unlock(&bufmgr_gem->lock);
+
+ return bo_gem->gtt_virtual;
+}
+
+void *drm_intel_gem_bo_map__cpu(drm_intel_bo *bo)
+{
+ drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+ drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+
+ if (bo_gem->mem_virtual)
+ return bo_gem->mem_virtual;
+
+ if (bo_gem->is_userptr) {
+ /* Return the same user ptr */
+ return bo_gem->user_virtual;
+ }
+
+ pthread_mutex_lock(&bufmgr_gem->lock);
+ if (!bo_gem->mem_virtual) {
+ struct drm_i915_gem_mmap mmap_arg;
+
+ if (bo_gem->map_count++ == 0)
+ drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
+
+ DBG("bo_map: %d (%s), map_count=%d\n",
+ bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
+
+ memclear(mmap_arg);
+ mmap_arg.handle = bo_gem->gem_handle;
+ mmap_arg.size = bo->size;
+ if (drmIoctl(bufmgr_gem->fd,
+ DRM_IOCTL_I915_GEM_MMAP,
+ &mmap_arg)) {
+ DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
+ __FILE__, __LINE__, bo_gem->gem_handle,
+ bo_gem->name, strerror(errno));
+ if (--bo_gem->map_count == 0)
+ drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
+ } else {
+ VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1));
+ bo_gem->mem_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr;
+ }
+ }
+ pthread_mutex_unlock(&bufmgr_gem->lock);
+
+ return bo_gem->mem_virtual;
+}
+
+void *drm_intel_gem_bo_map__wc(drm_intel_bo *bo)
+{
+ drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+ drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+
+ if (bo_gem->wc_virtual)
+ return bo_gem->wc_virtual;
+
+ if (bo_gem->is_userptr)
+ return NULL;
+
+ pthread_mutex_lock(&bufmgr_gem->lock);
+ if (!bo_gem->wc_virtual) {
+ struct drm_i915_gem_mmap mmap_arg;
+
+ if (bo_gem->map_count++ == 0)
+ drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
+
+ DBG("bo_map: %d (%s), map_count=%d\n",
+ bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
+
+ memclear(mmap_arg);
+ mmap_arg.handle = bo_gem->gem_handle;
+ mmap_arg.size = bo->size;
+ mmap_arg.flags = I915_MMAP_WC;
+ if (drmIoctl(bufmgr_gem->fd,
+ DRM_IOCTL_I915_GEM_MMAP,
+ &mmap_arg)) {
+ DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
+ __FILE__, __LINE__, bo_gem->gem_handle,
+ bo_gem->name, strerror(errno));
+ if (--bo_gem->map_count == 0)
+ drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
+ } else {
+ VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1));
+ bo_gem->wc_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr;
+ }
+ }
+ pthread_mutex_unlock(&bufmgr_gem->lock);
+
+ return bo_gem->wc_virtual;
+}
+
/**
* Initializes the GEM buffer manager, which uses the kernel to allocate, map,
* and manage map buffer objections.
@@ -3403,6 +3715,10 @@ drm_intel_bufmgr_gem_init(int fd, int ba
ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
bufmgr_gem->has_relaxed_fencing = ret == 0;
+ gp.param = I915_PARAM_HAS_EXEC_ASYNC;
+ ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
+ bufmgr_gem->has_exec_async = ret == 0;
+
bufmgr_gem->bufmgr.bo_alloc_userptr = check_bo_alloc_userptr;
gp.param = I915_PARAM_HAS_WAIT_TIMEOUT;
@@ -3506,7 +3822,6 @@ drm_intel_bufmgr_gem_init(int fd, int ba
drm_intel_gem_get_pipe_from_crtc_id;
bufmgr_gem->bufmgr.bo_references = drm_intel_gem_bo_references;
- DRMINITLISTHEAD(&bufmgr_gem->named);
init_cache_buckets(bufmgr_gem);
DRMINITLISTHEAD(&bufmgr_gem->vma_cache);
Index: xsrc/external/mit/libdrm/dist/radeon/radeon_cs_gem.c
diff -u xsrc/external/mit/libdrm/dist/radeon/radeon_cs_gem.c:1.6 xsrc/external/mit/libdrm/dist/radeon/radeon_cs_gem.c:1.7
--- xsrc/external/mit/libdrm/dist/radeon/radeon_cs_gem.c:1.6 Wed Aug 17 02:16:17 2016
+++ xsrc/external/mit/libdrm/dist/radeon/radeon_cs_gem.c Sat Mar 4 23:22:48 2017
@@ -189,7 +189,7 @@ static int cs_gem_write_reloc(struct rad
/* check domains */
if ((read_domain && write_domain) || (!read_domain && !write_domain)) {
/* in one CS a bo can only be in read or write domain but not
- * in read & write domain at the same sime
+ * in read & write domain at the same time
*/
return -EINVAL;
}
@@ -242,7 +242,7 @@ static int cs_gem_write_reloc(struct rad
}
/* new relocation */
if (csg->base.crelocs >= csg->nrelocs) {
- /* allocate more memory (TODO: should use a slab allocatore maybe) */
+ /* allocate more memory (TODO: should use a slab allocator maybe) */
uint32_t *tmp, size;
size = ((csg->nrelocs + 1) * sizeof(struct radeon_bo*));
tmp = (uint32_t*)realloc(csg->relocs_bo, size);
@@ -268,7 +268,7 @@ static int cs_gem_write_reloc(struct rad
reloc->flags = flags;
csg->chunks[1].length_dw += RELOC_SIZE;
radeon_bo_ref(bo);
- /* bo might be referenced from another context so have to use atomic opertions */
+ /* bo might be referenced from another context so have to use atomic operations */
atomic_add((atomic_t *)radeon_gem_get_reloc_in_cs(bo), cs->id);
cs->relocs_total_size += boi->size;
radeon_cs_write_dword((struct radeon_cs *)cs, 0xc0001000);
@@ -449,7 +449,7 @@ static int cs_gem_emit(struct radeon_cs_
&csg->cs, sizeof(struct drm_radeon_cs));
for (i = 0; i < csg->base.crelocs; i++) {
csg->relocs_bo[i]->space_accounted = 0;
- /* bo might be referenced from another context so have to use atomic opertions */
+ /* bo might be referenced from another context so have to use atomic operations */
atomic_dec((atomic_t *)radeon_gem_get_reloc_in_cs((struct radeon_bo*)csg->relocs_bo[i]), cs->id);
radeon_bo_unref((struct radeon_bo *)csg->relocs_bo[i]);
csg->relocs_bo[i] = NULL;
@@ -481,7 +481,7 @@ static int cs_gem_erase(struct radeon_cs
if (csg->relocs_bo) {
for (i = 0; i < csg->base.crelocs; i++) {
if (csg->relocs_bo[i]) {
- /* bo might be referenced from another context so have to use atomic opertions */
+ /* bo might be referenced from another context so have to use atomic operations */
atomic_dec((atomic_t *)radeon_gem_get_reloc_in_cs((struct radeon_bo*)csg->relocs_bo[i]), cs->id);
radeon_bo_unref((struct radeon_bo *)csg->relocs_bo[i]);
csg->relocs_bo[i] = NULL;
Index: xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c
diff -u xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c:1.8 xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c:1.9
--- xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c:1.8 Wed Aug 17 02:16:17 2016
+++ xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c Sat Mar 4 23:22:48 2017
@@ -42,6 +42,14 @@
#include "radeon_drm.h"
#include "radeon_surface.h"
+#define CIK_TILE_MODE_COLOR_2D 14
+#define CIK_TILE_MODE_COLOR_2D_SCANOUT 10
+#define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64 0
+#define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128 1
+#define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256 2
+#define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512 3
+#define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE 4
+
#define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
#define MAX2(A, B) ((A) > (B) ? (A) : (B))
#define MIN2(A, B) ((A) < (B) ? (A) : (B))
@@ -973,7 +981,7 @@ static int eg_surface_best(struct radeon
/* bankw or bankh greater than 1 increase alignment requirement, not
* sure if it's worth using smaller bankw & bankh to stick with 2D
* tiling on small surface rather than falling back to 1D tiling.
- * Use recommanded value based on tile size for now.
+ * Use recommended value based on tile size for now.
*
* fmask buffer has different optimal value figure them out once we
* use it.
Index: xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c
diff -u xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c:1.8 xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c:1.9
--- xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c:1.8 Wed Aug 17 02:16:17 2016
+++ xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c Sat Mar 4 23:22:48 2017
@@ -198,7 +198,7 @@ static void dump_encoders(struct device
static void dump_mode(drmModeModeInfo *mode)
{
- printf(" %s %d %d %d %d %d %d %d %d %d",
+ printf(" %s %d %d %d %d %d %d %d %d %d %d",
mode->name,
mode->vrefresh,
mode->hdisplay,
@@ -208,7 +208,8 @@ static void dump_mode(drmModeModeInfo *m
mode->vdisplay,
mode->vsync_start,
mode->vsync_end,
- mode->vtotal);
+ mode->vtotal,
+ mode->clock);
printf(" flags: ");
mode_flag_str(mode->flags);
@@ -705,6 +706,7 @@ struct pipe_arg {
};
struct plane_arg {
+ uint32_t plane_id; /* the id of plane to use */
uint32_t crtc_id; /* the id of CRTC to bind to */
bool has_position;
int32_t x, y;
@@ -959,7 +961,7 @@ static int set_plane(struct device *dev,
{
drmModePlane *ovr;
uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
- uint32_t plane_id = 0;
+ uint32_t plane_id;
struct bo *plane_bo;
uint32_t plane_flags = 0;
int crtc_x, crtc_y, crtc_w, crtc_h;
@@ -983,16 +985,26 @@ static int set_plane(struct device *dev,
return -1;
}
- for (i = 0; i < dev->resources->plane_res->count_planes && !plane_id; i++) {
+ plane_id = p->plane_id;
+
+ for (i = 0; i < dev->resources->plane_res->count_planes; i++) {
ovr = dev->resources->planes[i].plane;
- if (!ovr || !format_support(ovr, p->fourcc))
+ if (!ovr)
+ continue;
+
+ if (plane_id && plane_id != ovr->plane_id)
+ continue;
+
+ if (!format_support(ovr, p->fourcc))
continue;
- if ((ovr->possible_crtcs & (1 << pipe)) && !ovr->crtc_id)
+ if ((ovr->possible_crtcs & (1 << pipe)) && !ovr->crtc_id) {
plane_id = ovr->plane_id;
+ break;
+ }
}
- if (!plane_id) {
+ if (i == dev->resources->plane_res->count_planes) {
fprintf(stderr, "no unused plane available for CRTC %u\n",
crtc->crtc->crtc_id);
return -1;
@@ -1360,6 +1372,11 @@ static int parse_plane(struct plane_arg
{
char *end;
+ plane->plane_id = strtoul(p, &end, 10);
+ if (*end != '@')
+ return -EINVAL;
+
+ p = end + 1;
plane->crtc_id = strtoul(p, &end, 10);
if (*end != ':')
return -EINVAL;
@@ -1431,7 +1448,7 @@ 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 <crtc_id>:<w>x<h>[+<x>+<y>][*<scale>][@<format>]\tset a plane\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>[-<vrefresh>][@<format>]\tset a mode\n");
fprintf(stderr, "\t-C\ttest hw cursor\n");
fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
Index: xsrc/external/mit/pixman/dist/pixman/pixman-inlines.h
diff -u xsrc/external/mit/pixman/dist/pixman/pixman-inlines.h:1.3 xsrc/external/mit/pixman/dist/pixman/pixman-inlines.h:1.4
--- xsrc/external/mit/pixman/dist/pixman/pixman-inlines.h:1.3 Wed Jun 5 09:03:18 2013
+++ xsrc/external/mit/pixman/dist/pixman/pixman-inlines.h Sat Mar 4 23:22:48 2017
@@ -747,7 +747,8 @@ fast_composite_scaled_nearest ## scale_
#define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH(op,s,d,func) \
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_COVER (op,s,d,func), \
SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NONE (op,s,d,func), \
- SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_PAD (op,s,d,func)
+ SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_PAD (op,s,d,func), \
+ SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NORMAL (op,s,d,func)
/*****************************************************************************/
Index: xsrc/external/mit/pixman/dist/pixman/pixman-mmx.c
diff -u xsrc/external/mit/pixman/dist/pixman/pixman-mmx.c:1.2 xsrc/external/mit/pixman/dist/pixman/pixman-mmx.c:1.3
--- xsrc/external/mit/pixman/dist/pixman/pixman-mmx.c:1.2 Fri Jan 23 12:07:58 2015
+++ xsrc/external/mit/pixman/dist/pixman/pixman-mmx.c Sat Mar 4 23:22:48 2017
@@ -89,21 +89,7 @@ _mm_mulhi_pu16 (__m64 __A, __m64 __B)
return __A;
}
-# if defined( __OPTIMIZE__) && !defined(__clang__)
-extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
-_mm_shuffle_pi16 (__m64 __A, int8_t const __N)
-{
- __m64 ret;
-
- asm ("pshufw %2, %1, %0\n\t"
- : "=y" (ret)
- : "y" (__A), "K" (__N)
- );
-
- return ret;
-}
-# else
-# define _mm_shuffle_pi16(A, N) \
+# define _mm_shuffle_pi16(A, N) \
({ \
__m64 ret; \
\
@@ -114,7 +100,6 @@ _mm_shuffle_pi16 (__m64 __A, int8_t cons
\
ret; \
})
-# endif
# endif
#endif
@@ -3555,6 +3540,105 @@ mmx_composite_over_reverse_n_8888 (pixma
_mm_empty ();
}
+static force_inline void
+scaled_nearest_scanline_mmx_8888_8888_OVER (uint32_t* pd,
+ const uint32_t* ps,
+ int32_t w,
+ pixman_fixed_t vx,
+ pixman_fixed_t unit_x,
+ pixman_fixed_t src_width_fixed,
+ pixman_bool_t fully_transparent_src)
+{
+ if (fully_transparent_src)
+ return;
+
+ while (w)
+ {
+ __m64 d = load (pd);
+ __m64 s = load (ps + pixman_fixed_to_int (vx));
+ vx += unit_x;
+ while (vx >= 0)
+ vx -= src_width_fixed;
+
+ store8888 (pd, core_combine_over_u_pixel_mmx (s, d));
+ pd++;
+
+ w--;
+ }
+
+ _mm_empty ();
+}
+
+FAST_NEAREST_MAINLOOP (mmx_8888_8888_cover_OVER,
+ scaled_nearest_scanline_mmx_8888_8888_OVER,
+ uint32_t, uint32_t, COVER)
+FAST_NEAREST_MAINLOOP (mmx_8888_8888_none_OVER,
+ scaled_nearest_scanline_mmx_8888_8888_OVER,
+ uint32_t, uint32_t, NONE)
+FAST_NEAREST_MAINLOOP (mmx_8888_8888_pad_OVER,
+ scaled_nearest_scanline_mmx_8888_8888_OVER,
+ uint32_t, uint32_t, PAD)
+FAST_NEAREST_MAINLOOP (mmx_8888_8888_normal_OVER,
+ scaled_nearest_scanline_mmx_8888_8888_OVER,
+ uint32_t, uint32_t, NORMAL)
+
+static force_inline void
+scaled_nearest_scanline_mmx_8888_n_8888_OVER (const uint32_t * mask,
+ uint32_t * dst,
+ const uint32_t * src,
+ int32_t w,
+ pixman_fixed_t vx,
+ pixman_fixed_t unit_x,
+ pixman_fixed_t src_width_fixed,
+ pixman_bool_t zero_src)
+{
+ __m64 mm_mask;
+
+ if (zero_src || (*mask >> 24) == 0)
+ {
+ /* A workaround for https://gcc.gnu.org/PR47759 */
+ _mm_empty ();
+ return;
+ }
+
+ mm_mask = expand_alpha (load8888 (mask));
+
+ while (w)
+ {
+ uint32_t s = *(src + pixman_fixed_to_int (vx));
+ vx += unit_x;
+ while (vx >= 0)
+ vx -= src_width_fixed;
+
+ if (s)
+ {
+ __m64 ms = load8888 (&s);
+ __m64 alpha = expand_alpha (ms);
+ __m64 dest = load8888 (dst);
+
+ store8888 (dst, (in_over (ms, alpha, mm_mask, dest)));
+ }
+
+ dst++;
+ w--;
+ }
+
+ _mm_empty ();
+}
+
+FAST_NEAREST_MAINLOOP_COMMON (mmx_8888_n_8888_cover_OVER,
+ scaled_nearest_scanline_mmx_8888_n_8888_OVER,
+ uint32_t, uint32_t, uint32_t, COVER, TRUE, TRUE)
+FAST_NEAREST_MAINLOOP_COMMON (mmx_8888_n_8888_pad_OVER,
+ scaled_nearest_scanline_mmx_8888_n_8888_OVER,
+ uint32_t, uint32_t, uint32_t, PAD, TRUE, TRUE)
+FAST_NEAREST_MAINLOOP_COMMON (mmx_8888_n_8888_none_OVER,
+ scaled_nearest_scanline_mmx_8888_n_8888_OVER,
+ uint32_t, uint32_t, uint32_t, NONE, TRUE, TRUE)
+FAST_NEAREST_MAINLOOP_COMMON (mmx_8888_n_8888_normal_OVER,
+ scaled_nearest_scanline_mmx_8888_n_8888_OVER,
+ uint32_t, uint32_t, uint32_t, NORMAL, TRUE, TRUE)
+
#define BSHIFT ((1 << BILINEAR_INTERPOLATION_BITS))
#define BMSK (BSHIFT - 1)
@@ -3995,6 +4079,16 @@ static const pixman_fast_path_t mmx_fast
PIXMAN_STD_FAST_PATH (IN, a8, null, a8, mmx_composite_in_8_8 ),
PIXMAN_STD_FAST_PATH (IN, solid, a8, a8, mmx_composite_in_n_8_8 ),
+ SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mmx_8888_8888 ),
+ SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, mmx_8888_8888 ),
+ SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mmx_8888_8888 ),
+ SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, mmx_8888_8888 ),
+
+ SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mmx_8888_n_8888 ),
+ SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, mmx_8888_n_8888 ),
+ SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mmx_8888_n_8888 ),
+ SIMPLE_NEAREST_SOLID_MASK_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, mmx_8888_n_8888 ),
+
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, mmx_8888_8888 ),
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, mmx_8888_8888 ),
SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, mmx_8888_8888 ),
Index: xsrc/external/mit/pixman/dist/pixman/pixman-private.h
diff -u xsrc/external/mit/pixman/dist/pixman/pixman-private.h:1.5 xsrc/external/mit/pixman/dist/pixman/pixman-private.h:1.6
--- xsrc/external/mit/pixman/dist/pixman/pixman-private.h:1.5 Mon Mar 17 01:24:18 2014
+++ xsrc/external/mit/pixman/dist/pixman/pixman-private.h Sat Mar 4 23:22:48 2017
@@ -7,7 +7,7 @@
* The defines which are shared between C and assembly code
*/
-/* bilinear interpolation precision (must be <= 8) */
+/* bilinear interpolation precision (must be < 8) */
#define BILINEAR_INTERPOLATION_BITS 7
#define BILINEAR_INTERPOLATION_RANGE (1 << BILINEAR_INTERPOLATION_BITS)
@@ -345,8 +345,8 @@ typedef struct
float r_s, r_b;
float g_s, g_b;
float b_s, b_b;
- pixman_fixed_t left_x;
- pixman_fixed_t right_x;
+ pixman_fixed_48_16_t left_x;
+ pixman_fixed_48_16_t right_x;
pixman_gradient_stop_t *stops;
int num_stops;