diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c index 6459f11b1..c8fcd6220 100644 --- a/hw/xfree86/dri2/dri2.c +++ b/hw/xfree86/dri2/dri2.c @@ -1410,6 +1410,59 @@ get_prime_id(void) return -1; } +#include "pci_ids/pci_id_driver_map.h" + +static char * +dri2_probe_driver_name(ScreenPtr pScreen, DRI2InfoPtr info) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + struct pci_device *pdev = NULL; + int i, j; + + if (pEnt) + pdev = xf86GetPciInfoForEntity(pEnt->index); + + /* For non-PCI devices, just assume that the 3D driver is named + * the same as the kernel driver. This is currently true for vc4 + * and msm (freedreno). + */ + if (!pdev) { + drmVersionPtr version = drmGetVersion(info->fd); + char *kernel_driver; + + if (!version) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[DRI2] Couldn't drmGetVersion() on non-PCI device, " + "no driver name found.\n"); + return NULL; + } + + kernel_driver = strndup(version->name, version->name_len); + drmFreeVersion(version); + return kernel_driver; + } + + for (i = 0; driver_map[i].driver; i++) { + if (pdev->vendor_id != driver_map[i].vendor_id) + continue; + + if (driver_map[i].num_chips_ids == -1) + return strdup(driver_map[i].driver); + + for (j = 0; j < driver_map[i].num_chips_ids; j++) { + if (driver_map[i].chip_ids[j] == pdev->device_id) + return strdup(driver_map[i].driver); + } + } + + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[DRI2] No driver mapping found for PCI device " + "0x%04x / 0x%04x\n", + pdev->vendor_id, pdev->device_id); + return NULL; +} + Bool DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) { @@ -1524,7 +1577,14 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) ds->driverNames = malloc(sizeof(*ds->driverNames)); if (!ds->driverNames) goto err_out; - ds->driverNames[0] = info->driverName; + + if (info->driverName) { + ds->driverNames[0] = info->driverName; + } else { + ds->driverNames[0] = dri2_probe_driver_name(pScreen, info); + if (!ds->driverNames[0]) + return FALSE; + } } else { ds->numDrivers = info->numDrivers; diff --git a/hw/xfree86/dri2/pci_ids/i810_pci_ids.h b/hw/xfree86/dri2/pci_ids/i810_pci_ids.h new file mode 100644 index 000000000..7f681925d --- /dev/null +++ b/hw/xfree86/dri2/pci_ids/i810_pci_ids.h @@ -0,0 +1,4 @@ +CHIPSET(0x7121, I810, i8xx) +CHIPSET(0x7123, I810_DC100, i8xx) +CHIPSET(0x7125, I810_E, i8xx) +CHIPSET(0x1132, I815, i8xx) diff --git a/hw/xfree86/dri2/pci_ids/i915_pci_ids.h b/hw/xfree86/dri2/pci_ids/i915_pci_ids.h new file mode 100644 index 000000000..7d51975c3 --- /dev/null +++ b/hw/xfree86/dri2/pci_ids/i915_pci_ids.h @@ -0,0 +1,15 @@ +CHIPSET(0x3577, I830_M, "Intel(R) 830M") +CHIPSET(0x2562, 845_G, "Intel(R) 845G") +CHIPSET(0x3582, I855_GM, "Intel(R) 852GM/855GM") +CHIPSET(0x2572, I865_G, "Intel(R) 865G") +CHIPSET(0x2582, I915_G, "Intel(R) 915G") +CHIPSET(0x258A, E7221_G, "Intel(R) E7221G (i915)") +CHIPSET(0x2592, I915_GM, "Intel(R) 915GM") +CHIPSET(0x2772, I945_G, "Intel(R) 945G") +CHIPSET(0x27A2, I945_GM, "Intel(R) 945GM") +CHIPSET(0x27AE, I945_GME, "Intel(R) 945GME") +CHIPSET(0x29B2, Q35_G, "Intel(R) Q35") +CHIPSET(0x29C2, G33_G, "Intel(R) G33") +CHIPSET(0x29D2, Q33_G, "Intel(R) Q33") +CHIPSET(0xA011, IGD_GM, "Intel(R) IGD") +CHIPSET(0xA001, IGD_G, "Intel(R) IGD") diff --git a/hw/xfree86/dri2/pci_ids/i965_pci_ids.h b/hw/xfree86/dri2/pci_ids/i965_pci_ids.h new file mode 100644 index 000000000..2e04301fb --- /dev/null +++ b/hw/xfree86/dri2/pci_ids/i965_pci_ids.h @@ -0,0 +1,115 @@ +CHIPSET(0x29A2, i965, "Intel(R) 965G") +CHIPSET(0x2992, i965, "Intel(R) 965Q") +CHIPSET(0x2982, i965, "Intel(R) 965G") +CHIPSET(0x2972, i965, "Intel(R) 946GZ") +CHIPSET(0x2A02, i965, "Intel(R) 965GM") +CHIPSET(0x2A12, i965, "Intel(R) 965GME/GLE") +CHIPSET(0x2A42, g4x, "Mobile Intel® GM45 Express Chipset") +CHIPSET(0x2E02, g4x, "Intel(R) Integrated Graphics Device") +CHIPSET(0x2E12, g4x, "Intel(R) Q45/Q43") +CHIPSET(0x2E22, g4x, "Intel(R) G45/G43") +CHIPSET(0x2E32, g4x, "Intel(R) G41") +CHIPSET(0x2E42, g4x, "Intel(R) B43") +CHIPSET(0x2E92, g4x, "Intel(R) B43") +CHIPSET(0x0042, ilk, "Intel(R) Ironlake Desktop") +CHIPSET(0x0046, ilk, "Intel(R) Ironlake Mobile") +CHIPSET(0x0102, snb_gt1, "Intel(R) Sandybridge Desktop") +CHIPSET(0x0112, snb_gt2, "Intel(R) Sandybridge Desktop") +CHIPSET(0x0122, snb_gt2, "Intel(R) Sandybridge Desktop") +CHIPSET(0x0106, snb_gt1, "Intel(R) Sandybridge Mobile") +CHIPSET(0x0116, snb_gt2, "Intel(R) Sandybridge Mobile") +CHIPSET(0x0126, snb_gt2, "Intel(R) Sandybridge Mobile") +CHIPSET(0x010A, snb_gt1, "Intel(R) Sandybridge Server") +CHIPSET(0x0152, ivb_gt1, "Intel(R) Ivybridge Desktop") +CHIPSET(0x0162, ivb_gt2, "Intel(R) Ivybridge Desktop") +CHIPSET(0x0156, ivb_gt1, "Intel(R) Ivybridge Mobile") +CHIPSET(0x0166, ivb_gt2, "Intel(R) Ivybridge Mobile") +CHIPSET(0x015a, ivb_gt1, "Intel(R) Ivybridge Server") +CHIPSET(0x016a, ivb_gt2, "Intel(R) Ivybridge Server") +CHIPSET(0x0402, hsw_gt1, "Intel(R) Haswell Desktop") +CHIPSET(0x0412, hsw_gt2, "Intel(R) Haswell Desktop") +CHIPSET(0x0422, hsw_gt3, "Intel(R) Haswell Desktop") +CHIPSET(0x0406, hsw_gt1, "Intel(R) Haswell Mobile") +CHIPSET(0x0416, hsw_gt2, "Intel(R) Haswell Mobile") +CHIPSET(0x0426, hsw_gt3, "Intel(R) Haswell Mobile") +CHIPSET(0x040A, hsw_gt1, "Intel(R) Haswell Server") +CHIPSET(0x041A, hsw_gt2, "Intel(R) Haswell Server") +CHIPSET(0x042A, hsw_gt3, "Intel(R) Haswell Server") +CHIPSET(0x040B, hsw_gt1, "Intel(R) Haswell") +CHIPSET(0x041B, hsw_gt2, "Intel(R) Haswell") +CHIPSET(0x042B, hsw_gt3, "Intel(R) Haswell") +CHIPSET(0x040E, hsw_gt1, "Intel(R) Haswell") +CHIPSET(0x041E, hsw_gt2, "Intel(R) Haswell") +CHIPSET(0x042E, hsw_gt3, "Intel(R) Haswell") +CHIPSET(0x0C02, hsw_gt1, "Intel(R) Haswell Desktop") +CHIPSET(0x0C12, hsw_gt2, "Intel(R) Haswell Desktop") +CHIPSET(0x0C22, hsw_gt3, "Intel(R) Haswell Desktop") +CHIPSET(0x0C06, hsw_gt1, "Intel(R) Haswell Mobile") +CHIPSET(0x0C16, hsw_gt2, "Intel(R) Haswell Mobile") +CHIPSET(0x0C26, hsw_gt3, "Intel(R) Haswell Mobile") +CHIPSET(0x0C0A, hsw_gt1, "Intel(R) Haswell Server") +CHIPSET(0x0C1A, hsw_gt2, "Intel(R) Haswell Server") +CHIPSET(0x0C2A, hsw_gt3, "Intel(R) Haswell Server") +CHIPSET(0x0C0B, hsw_gt1, "Intel(R) Haswell") +CHIPSET(0x0C1B, hsw_gt2, "Intel(R) Haswell") +CHIPSET(0x0C2B, hsw_gt3, "Intel(R) Haswell") +CHIPSET(0x0C0E, hsw_gt1, "Intel(R) Haswell") +CHIPSET(0x0C1E, hsw_gt2, "Intel(R) Haswell") +CHIPSET(0x0C2E, hsw_gt3, "Intel(R) Haswell") +CHIPSET(0x0A02, hsw_gt1, "Intel(R) Haswell Desktop") +CHIPSET(0x0A12, hsw_gt2, "Intel(R) Haswell Desktop") +CHIPSET(0x0A22, hsw_gt3, "Intel(R) Haswell Desktop") +CHIPSET(0x0A06, hsw_gt1, "Intel(R) Haswell Mobile") +CHIPSET(0x0A16, hsw_gt2, "Intel(R) Haswell Mobile") +CHIPSET(0x0A26, hsw_gt3, "Intel(R) Haswell Mobile") +CHIPSET(0x0A0A, hsw_gt1, "Intel(R) Haswell Server") +CHIPSET(0x0A1A, hsw_gt2, "Intel(R) Haswell Server") +CHIPSET(0x0A2A, hsw_gt3, "Intel(R) Haswell Server") +CHIPSET(0x0A0B, hsw_gt1, "Intel(R) Haswell") +CHIPSET(0x0A1B, hsw_gt2, "Intel(R) Haswell") +CHIPSET(0x0A2B, hsw_gt3, "Intel(R) Haswell") +CHIPSET(0x0A0E, hsw_gt1, "Intel(R) Haswell") +CHIPSET(0x0A1E, hsw_gt2, "Intel(R) Haswell") +CHIPSET(0x0A2E, hsw_gt3, "Intel(R) Haswell") +CHIPSET(0x0D02, hsw_gt1, "Intel(R) Haswell Desktop") +CHIPSET(0x0D12, hsw_gt2, "Intel(R) Haswell Desktop") +CHIPSET(0x0D22, hsw_gt3, "Intel(R) Haswell Desktop") +CHIPSET(0x0D06, hsw_gt1, "Intel(R) Haswell Mobile") +CHIPSET(0x0D16, hsw_gt2, "Intel(R) Haswell Mobile") +CHIPSET(0x0D26, hsw_gt3, "Intel(R) Haswell Mobile") +CHIPSET(0x0D0A, hsw_gt1, "Intel(R) Haswell Server") +CHIPSET(0x0D1A, hsw_gt2, "Intel(R) Haswell Server") +CHIPSET(0x0D2A, hsw_gt3, "Intel(R) Haswell") +CHIPSET(0x0D0B, hsw_gt1, "Intel(R) Haswell") +CHIPSET(0x0D1B, hsw_gt2, "Intel(R) Haswell") +CHIPSET(0x0D2B, hsw_gt3, "Intel(R) Haswell") +CHIPSET(0x0D0E, hsw_gt1, "Intel(R) Haswell") +CHIPSET(0x0D1E, hsw_gt2, "Intel(R) Haswell") +CHIPSET(0x0D2E, hsw_gt3, "Intel(R) Haswell") +CHIPSET(0x0F31, byt, "Intel(R) Bay Trail") +CHIPSET(0x0F32, byt, "Intel(R) Bay Trail") +CHIPSET(0x0F33, byt, "Intel(R) Bay Trail") +CHIPSET(0x0157, byt, "Intel(R) Bay Trail") +CHIPSET(0x0155, byt, "Intel(R) Bay Trail") +CHIPSET(0x1602, bdw_gt1, "Intel(R) Broadwell GT1") +CHIPSET(0x1606, bdw_gt1, "Intel(R) Broadwell GT1") +CHIPSET(0x160A, bdw_gt1, "Intel(R) Broadwell GT1") +CHIPSET(0x160B, bdw_gt1, "Intel(R) Broadwell GT1") +CHIPSET(0x160D, bdw_gt1, "Intel(R) Broadwell GT1") +CHIPSET(0x160E, bdw_gt1, "Intel(R) Broadwell GT1") +CHIPSET(0x1612, bdw_gt2, "Intel(R) HD Graphics 5600 (Broadwell GT2)") +CHIPSET(0x1616, bdw_gt2, "Intel(R) HD Graphics 5500 (Broadwell GT2)") +CHIPSET(0x161A, bdw_gt2, "Intel(R) Broadwell GT2") +CHIPSET(0x161B, bdw_gt2, "Intel(R) Broadwell GT2") +CHIPSET(0x161D, bdw_gt2, "Intel(R) Broadwell GT2") +CHIPSET(0x161E, bdw_gt2, "Intel(R) HD Graphics 5300 (Broadwell GT2)") +CHIPSET(0x1622, bdw_gt3, "Intel(R) Iris Pro 6200 (Broadwell GT3e)") +CHIPSET(0x1626, bdw_gt3, "Intel(R) HD Graphics 6000 (Broadwell GT3)") +CHIPSET(0x162A, bdw_gt3, "Intel(R) Iris Pro P6300 (Broadwell GT3e)") +CHIPSET(0x162B, bdw_gt3, "Intel(R) Iris 6100 (Broadwell GT3)") +CHIPSET(0x162D, bdw_gt3, "Intel(R) Broadwell GT3") +CHIPSET(0x162E, bdw_gt3, "Intel(R) Broadwell GT3") +CHIPSET(0x22B0, chv, "Intel(R) Cherryview") +CHIPSET(0x22B1, chv, "Intel(R) Cherryview") +CHIPSET(0x22B2, chv, "Intel(R) Cherryview") +CHIPSET(0x22B3, chv, "Intel(R) Cherryview") diff --git a/hw/xfree86/dri2/pci_ids/pci_id_driver_map.h b/hw/xfree86/dri2/pci_ids/pci_id_driver_map.h new file mode 100644 index 000000000..8a97c6f31 --- /dev/null +++ b/hw/xfree86/dri2/pci_ids/pci_id_driver_map.h @@ -0,0 +1,80 @@ +#ifndef _PCI_ID_DRIVER_MAP_H_ +#define _PCI_ID_DRIVER_MAP_H_ + +#include + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#endif + +static const int i915_chip_ids[] = { +#define CHIPSET(chip, desc, name) chip, +#include "pci_ids/i915_pci_ids.h" +#undef CHIPSET +}; + +static const int i965_chip_ids[] = { +#define CHIPSET(chip, family, name) chip, +#include "pci_ids/i965_pci_ids.h" +#undef CHIPSET +}; + +#ifndef DRIVER_MAP_GALLIUM_ONLY +static const int r100_chip_ids[] = { +#define CHIPSET(chip, name, family) chip, +#include "pci_ids/radeon_pci_ids.h" +#undef CHIPSET +}; + +static const int r200_chip_ids[] = { +#define CHIPSET(chip, name, family) chip, +#include "pci_ids/r200_pci_ids.h" +#undef CHIPSET +}; +#endif + +static const int r300_chip_ids[] = { +#define CHIPSET(chip, name, family) chip, +#include "pci_ids/r300_pci_ids.h" +#undef CHIPSET +}; + +static const int r600_chip_ids[] = { +#define CHIPSET(chip, name, family) chip, +#include "pci_ids/r600_pci_ids.h" +#undef CHIPSET +}; + +static const int radeonsi_chip_ids[] = { +#define CHIPSET(chip, name, family) chip, +#include "pci_ids/radeonsi_pci_ids.h" +#undef CHIPSET +}; + +static const int vmwgfx_chip_ids[] = { +#define CHIPSET(chip, name, family) chip, +#include "pci_ids/vmwgfx_pci_ids.h" +#undef CHIPSET +}; + +static const struct { + int vendor_id; + const char *driver; + const int *chip_ids; + int num_chips_ids; +} driver_map[] = { + { 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids) }, + { 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids) }, +#ifndef DRIVER_MAP_GALLIUM_ONLY + { 0x1002, "radeon", r100_chip_ids, ARRAY_SIZE(r100_chip_ids) }, + { 0x1002, "r200", r200_chip_ids, ARRAY_SIZE(r200_chip_ids) }, +#endif + { 0x1002, "r300", r300_chip_ids, ARRAY_SIZE(r300_chip_ids) }, + { 0x1002, "r600", r600_chip_ids, ARRAY_SIZE(r600_chip_ids) }, + { 0x1002, "radeonsi", radeonsi_chip_ids, ARRAY_SIZE(radeonsi_chip_ids) }, + { 0x10de, "nouveau", NULL, -1 }, + { 0x15ad, "vmwgfx", vmwgfx_chip_ids, ARRAY_SIZE(vmwgfx_chip_ids) }, + { 0x0000, NULL, NULL, 0 }, +}; + +#endif /* _PCI_ID_DRIVER_MAP_H_ */ diff --git a/hw/xfree86/dri2/pci_ids/r200_pci_ids.h b/hw/xfree86/dri2/pci_ids/r200_pci_ids.h new file mode 100644 index 000000000..f857ca704 --- /dev/null +++ b/hw/xfree86/dri2/pci_ids/r200_pci_ids.h @@ -0,0 +1,24 @@ +CHIPSET(0x5148, R200_QH, R200) +CHIPSET(0x514C, R200_QL, R200) +CHIPSET(0x514D, R200_QM, R200) +CHIPSET(0x4242, R200_BB, R200) + +CHIPSET(0x4966, RV250_If, RV250) +CHIPSET(0x4967, RV250_Ig, RV250) +CHIPSET(0x4C64, RV250_Ld, RV250) +CHIPSET(0x4C66, RV250_Lf, RV250) +CHIPSET(0x4C67, RV250_Lg, RV250) + +CHIPSET(0x4C6E, RV280_4C6E, RV280) +CHIPSET(0x5960, RV280_5960, RV280) +CHIPSET(0x5961, RV280_5961, RV280) +CHIPSET(0x5962, RV280_5962, RV280) +CHIPSET(0x5964, RV280_5964, RV280) +CHIPSET(0x5965, RV280_5965, RV280) +CHIPSET(0x5C61, RV280_5C61, RV280) +CHIPSET(0x5C63, RV280_5C63, RV280) + +CHIPSET(0x5834, RS300_5834, RS300) +CHIPSET(0x5835, RS300_5835, RS300) +CHIPSET(0x7834, RS350_7834, RS300) +CHIPSET(0x7835, RS350_7835, RS300) diff --git a/hw/xfree86/dri2/pci_ids/r300_pci_ids.h b/hw/xfree86/dri2/pci_ids/r300_pci_ids.h new file mode 100644 index 000000000..791026ae7 --- /dev/null +++ b/hw/xfree86/dri2/pci_ids/r300_pci_ids.h @@ -0,0 +1,227 @@ +CHIPSET(0x4144, R300_AD, R300) +CHIPSET(0x4145, R300_AE, R300) +CHIPSET(0x4146, R300_AF, R300) +CHIPSET(0x4147, R300_AG, R300) +CHIPSET(0x4E44, R300_ND, R300) +CHIPSET(0x4E45, R300_NE, R300) +CHIPSET(0x4E46, R300_NF, R300) +CHIPSET(0x4E47, R300_NG, R300) + +CHIPSET(0x4E48, R350_NH, R350) +CHIPSET(0x4E49, R350_NI, R350) +CHIPSET(0x4E4B, R350_NK, R350) +CHIPSET(0x4148, R350_AH, R350) +CHIPSET(0x4149, R350_AI, R350) +CHIPSET(0x414A, R350_AJ, R350) +CHIPSET(0x414B, R350_AK, R350) +CHIPSET(0x4E4A, R360_NJ, R350) + +CHIPSET(0x4150, RV350_AP, RV350) +CHIPSET(0x4151, RV350_AQ, RV350) +CHIPSET(0x4152, RV350_AR, RV350) +CHIPSET(0x4153, RV350_AS, RV350) +CHIPSET(0x4154, RV350_AT, RV350) +CHIPSET(0x4155, RV350_AU, RV350) +CHIPSET(0x4156, RV350_AV, RV350) +CHIPSET(0x4E50, RV350_NP, RV350) +CHIPSET(0x4E51, RV350_NQ, RV350) +CHIPSET(0x4E52, RV350_NR, RV350) +CHIPSET(0x4E53, RV350_NS, RV350) +CHIPSET(0x4E54, RV350_NT, RV350) +CHIPSET(0x4E56, RV350_NV, RV350) + +CHIPSET(0x5460, RV370_5460, RV370) +CHIPSET(0x5462, RV370_5462, RV370) +CHIPSET(0x5464, RV370_5464, RV370) +CHIPSET(0x5B60, RV370_5B60, RV370) +CHIPSET(0x5B62, RV370_5B62, RV370) +CHIPSET(0x5B63, RV370_5B63, RV370) +CHIPSET(0x5B64, RV370_5B64, RV370) +CHIPSET(0x5B65, RV370_5B65, RV370) + +CHIPSET(0x3150, RV380_3150, RV380) +CHIPSET(0x3151, RV380_3151, RV380) +CHIPSET(0x3152, RV380_3152, RV380) +CHIPSET(0x3154, RV380_3154, RV380) +CHIPSET(0x3155, RV380_3155, RV380) +CHIPSET(0x3E50, RV380_3E50, RV380) +CHIPSET(0x3E54, RV380_3E54, RV380) + +CHIPSET(0x4A48, R420_JH, R420) +CHIPSET(0x4A49, R420_JI, R420) +CHIPSET(0x4A4A, R420_JJ, R420) +CHIPSET(0x4A4B, R420_JK, R420) +CHIPSET(0x4A4C, R420_JL, R420) +CHIPSET(0x4A4D, R420_JM, R420) +CHIPSET(0x4A4E, R420_JN, R420) +CHIPSET(0x4A4F, R420_JO, R420) +CHIPSET(0x4A50, R420_JP, R420) +CHIPSET(0x4A54, R420_JT, R420) + +CHIPSET(0x5548, R423_UH, R423) +CHIPSET(0x5549, R423_UI, R423) +CHIPSET(0x554A, R423_UJ, R423) +CHIPSET(0x554B, R423_UK, R423) +CHIPSET(0x5550, R423_5550, R423) +CHIPSET(0x5551, R423_UQ, R423) +CHIPSET(0x5552, R423_UR, R423) +CHIPSET(0x5554, R423_UT, R423) +CHIPSET(0x5D57, R423_5D57, R423) + +CHIPSET(0x554C, R430_554C, R430) +CHIPSET(0x554D, R430_554D, R430) +CHIPSET(0x554E, R430_554E, R430) +CHIPSET(0x554F, R430_554F, R430) +CHIPSET(0x5D48, R430_5D48, R430) +CHIPSET(0x5D49, R430_5D49, R430) +CHIPSET(0x5D4A, R430_5D4A, R430) + +CHIPSET(0x5D4C, R480_5D4C, R480) +CHIPSET(0x5D4D, R480_5D4D, R480) +CHIPSET(0x5D4E, R480_5D4E, R480) +CHIPSET(0x5D4F, R480_5D4F, R480) +CHIPSET(0x5D50, R480_5D50, R480) +CHIPSET(0x5D52, R480_5D52, R480) + +CHIPSET(0x4B48, R481_4B48, R481) +CHIPSET(0x4B49, R481_4B49, R481) +CHIPSET(0x4B4A, R481_4B4A, R481) +CHIPSET(0x4B4B, R481_4B4B, R481) +CHIPSET(0x4B4C, R481_4B4C, R481) + +CHIPSET(0x564A, RV410_564A, RV410) +CHIPSET(0x564B, RV410_564B, RV410) +CHIPSET(0x564F, RV410_564F, RV410) +CHIPSET(0x5652, RV410_5652, RV410) +CHIPSET(0x5653, RV410_5653, RV410) +CHIPSET(0x5657, RV410_5657, RV410) +CHIPSET(0x5E48, RV410_5E48, RV410) +CHIPSET(0x5E4A, RV410_5E4A, RV410) +CHIPSET(0x5E4B, RV410_5E4B, RV410) +CHIPSET(0x5E4C, RV410_5E4C, RV410) +CHIPSET(0x5E4D, RV410_5E4D, RV410) +CHIPSET(0x5E4F, RV410_5E4F, RV410) + +CHIPSET(0x5A41, RS400_5A41, RS400) +CHIPSET(0x5A42, RS400_5A42, RS400) + +CHIPSET(0x5A61, RC410_5A61, RC410) +CHIPSET(0x5A62, RC410_5A62, RC410) + +CHIPSET(0x5954, RS480_5954, RS480) +CHIPSET(0x5955, RS480_5955, RS480) +CHIPSET(0x5974, RS482_5974, RS480) +CHIPSET(0x5975, RS482_5975, RS480) + +CHIPSET(0x7100, R520_7100, R520) +CHIPSET(0x7101, R520_7101, R520) +CHIPSET(0x7102, R520_7102, R520) +CHIPSET(0x7103, R520_7103, R520) +CHIPSET(0x7104, R520_7104, R520) +CHIPSET(0x7105, R520_7105, R520) +CHIPSET(0x7106, R520_7106, R520) +CHIPSET(0x7108, R520_7108, R520) +CHIPSET(0x7109, R520_7109, R520) +CHIPSET(0x710A, R520_710A, R520) +CHIPSET(0x710B, R520_710B, R520) +CHIPSET(0x710C, R520_710C, R520) +CHIPSET(0x710E, R520_710E, R520) +CHIPSET(0x710F, R520_710F, R520) + +CHIPSET(0x7140, RV515_7140, RV515) +CHIPSET(0x7141, RV515_7141, RV515) +CHIPSET(0x7142, RV515_7142, RV515) +CHIPSET(0x7143, RV515_7143, RV515) +CHIPSET(0x7144, RV515_7144, RV515) +CHIPSET(0x7145, RV515_7145, RV515) +CHIPSET(0x7146, RV515_7146, RV515) +CHIPSET(0x7147, RV515_7147, RV515) +CHIPSET(0x7149, RV515_7149, RV515) +CHIPSET(0x714A, RV515_714A, RV515) +CHIPSET(0x714B, RV515_714B, RV515) +CHIPSET(0x714C, RV515_714C, RV515) +CHIPSET(0x714D, RV515_714D, RV515) +CHIPSET(0x714E, RV515_714E, RV515) +CHIPSET(0x714F, RV515_714F, RV515) +CHIPSET(0x7151, RV515_7151, RV515) +CHIPSET(0x7152, RV515_7152, RV515) +CHIPSET(0x7153, RV515_7153, RV515) +CHIPSET(0x715E, RV515_715E, RV515) +CHIPSET(0x715F, RV515_715F, RV515) +CHIPSET(0x7180, RV515_7180, RV515) +CHIPSET(0x7181, RV515_7181, RV515) +CHIPSET(0x7183, RV515_7183, RV515) +CHIPSET(0x7186, RV515_7186, RV515) +CHIPSET(0x7187, RV515_7187, RV515) +CHIPSET(0x7188, RV515_7188, RV515) +CHIPSET(0x718A, RV515_718A, RV515) +CHIPSET(0x718B, RV515_718B, RV515) +CHIPSET(0x718C, RV515_718C, RV515) +CHIPSET(0x718D, RV515_718D, RV515) +CHIPSET(0x718F, RV515_718F, RV515) +CHIPSET(0x7193, RV515_7193, RV515) +CHIPSET(0x7196, RV515_7196, RV515) +CHIPSET(0x719B, RV515_719B, RV515) +CHIPSET(0x719F, RV515_719F, RV515) +CHIPSET(0x7200, RV515_7200, RV515) +CHIPSET(0x7210, RV515_7210, RV515) +CHIPSET(0x7211, RV515_7211, RV515) + +CHIPSET(0x71C0, RV530_71C0, RV530) +CHIPSET(0x71C1, RV530_71C1, RV530) +CHIPSET(0x71C2, RV530_71C2, RV530) +CHIPSET(0x71C3, RV530_71C3, RV530) +CHIPSET(0x71C4, RV530_71C4, RV530) +CHIPSET(0x71C5, RV530_71C5, RV530) +CHIPSET(0x71C6, RV530_71C6, RV530) +CHIPSET(0x71C7, RV530_71C7, RV530) +CHIPSET(0x71CD, RV530_71CD, RV530) +CHIPSET(0x71CE, RV530_71CE, RV530) +CHIPSET(0x71D2, RV530_71D2, RV530) +CHIPSET(0x71D4, RV530_71D4, RV530) +CHIPSET(0x71D5, RV530_71D5, RV530) +CHIPSET(0x71D6, RV530_71D6, RV530) +CHIPSET(0x71DA, RV530_71DA, RV530) +CHIPSET(0x71DE, RV530_71DE, RV530) + +CHIPSET(0x7281, RV560_7281, RV560) +CHIPSET(0x7283, RV560_7283, RV560) +CHIPSET(0x7287, RV560_7287, RV560) +CHIPSET(0x7290, RV560_7290, RV560) +CHIPSET(0x7291, RV560_7291, RV560) +CHIPSET(0x7293, RV560_7293, RV560) +CHIPSET(0x7297, RV560_7297, RV560) + +CHIPSET(0x7280, RV570_7280, RV570) +CHIPSET(0x7288, RV570_7288, RV570) +CHIPSET(0x7289, RV570_7289, RV570) +CHIPSET(0x728B, RV570_728B, RV570) +CHIPSET(0x728C, RV570_728C, RV570) + +CHIPSET(0x7240, R580_7240, R580) +CHIPSET(0x7243, R580_7243, R580) +CHIPSET(0x7244, R580_7244, R580) +CHIPSET(0x7245, R580_7245, R580) +CHIPSET(0x7246, R580_7246, R580) +CHIPSET(0x7247, R580_7247, R580) +CHIPSET(0x7248, R580_7248, R580) +CHIPSET(0x7249, R580_7249, R580) +CHIPSET(0x724A, R580_724A, R580) +CHIPSET(0x724B, R580_724B, R580) +CHIPSET(0x724C, R580_724C, R580) +CHIPSET(0x724D, R580_724D, R580) +CHIPSET(0x724E, R580_724E, R580) +CHIPSET(0x724F, R580_724F, R580) +CHIPSET(0x7284, R580_7284, R580) + +CHIPSET(0x793F, RS600_793F, RS600) +CHIPSET(0x7941, RS600_7941, RS600) +CHIPSET(0x7942, RS600_7942, RS600) + +CHIPSET(0x791E, RS690_791E, RS690) +CHIPSET(0x791F, RS690_791F, RS690) + +CHIPSET(0x796C, RS740_796C, RS740) +CHIPSET(0x796D, RS740_796D, RS740) +CHIPSET(0x796E, RS740_796E, RS740) +CHIPSET(0x796F, RS740_796F, RS740) diff --git a/hw/xfree86/dri2/pci_ids/r600_pci_ids.h b/hw/xfree86/dri2/pci_ids/r600_pci_ids.h new file mode 100644 index 000000000..533c9f3fc --- /dev/null +++ b/hw/xfree86/dri2/pci_ids/r600_pci_ids.h @@ -0,0 +1,327 @@ +CHIPSET(0x9400, R600_9400, R600) +CHIPSET(0x9401, R600_9401, R600) +CHIPSET(0x9402, R600_9402, R600) +CHIPSET(0x9403, R600_9403, R600) +CHIPSET(0x9405, R600_9405, R600) +CHIPSET(0x940A, R600_940A, R600) +CHIPSET(0x940B, R600_940B, R600) +CHIPSET(0x940F, R600_940F, R600) + +CHIPSET(0x94C0, RV610_94C0, RV610) +CHIPSET(0x94C1, RV610_94C1, RV610) +CHIPSET(0x94C3, RV610_94C3, RV610) +CHIPSET(0x94C4, RV610_94C4, RV610) +CHIPSET(0x94C5, RV610_94C5, RV610) +CHIPSET(0x94C6, RV610_94C6, RV610) +CHIPSET(0x94C7, RV610_94C7, RV610) +CHIPSET(0x94C8, RV610_94C8, RV610) +CHIPSET(0x94C9, RV610_94C9, RV610) +CHIPSET(0x94CB, RV610_94CB, RV610) +CHIPSET(0x94CC, RV610_94CC, RV610) +CHIPSET(0x94CD, RV610_94CD, RV610) + +CHIPSET(0x9580, RV630_9580, RV630) +CHIPSET(0x9581, RV630_9581, RV630) +CHIPSET(0x9583, RV630_9583, RV630) +CHIPSET(0x9586, RV630_9586, RV630) +CHIPSET(0x9587, RV630_9587, RV630) +CHIPSET(0x9588, RV630_9588, RV630) +CHIPSET(0x9589, RV630_9589, RV630) +CHIPSET(0x958A, RV630_958A, RV630) +CHIPSET(0x958B, RV630_958B, RV630) +CHIPSET(0x958C, RV630_958C, RV630) +CHIPSET(0x958D, RV630_958D, RV630) +CHIPSET(0x958E, RV630_958E, RV630) +CHIPSET(0x958F, RV630_958F, RV630) + +CHIPSET(0x9500, RV670_9500, RV670) +CHIPSET(0x9501, RV670_9501, RV670) +CHIPSET(0x9504, RV670_9504, RV670) +CHIPSET(0x9505, RV670_9505, RV670) +CHIPSET(0x9506, RV670_9506, RV670) +CHIPSET(0x9507, RV670_9507, RV670) +CHIPSET(0x9508, RV670_9508, RV670) +CHIPSET(0x9509, RV670_9509, RV670) +CHIPSET(0x950F, RV670_950F, RV670) +CHIPSET(0x9511, RV670_9511, RV670) +CHIPSET(0x9515, RV670_9515, RV670) +CHIPSET(0x9517, RV670_9517, RV670) +CHIPSET(0x9519, RV670_9519, RV670) + +CHIPSET(0x95C0, RV620_95C0, RV620) +CHIPSET(0x95C2, RV620_95C2, RV620) +CHIPSET(0x95C4, RV620_95C4, RV620) +CHIPSET(0x95C5, RV620_95C5, RV620) +CHIPSET(0x95C6, RV620_95C6, RV620) +CHIPSET(0x95C7, RV620_95C7, RV620) +CHIPSET(0x95C9, RV620_95C9, RV620) +CHIPSET(0x95CC, RV620_95CC, RV620) +CHIPSET(0x95CD, RV620_95CD, RV620) +CHIPSET(0x95CE, RV620_95CE, RV620) +CHIPSET(0x95CF, RV620_95CF, RV620) + +CHIPSET(0x9590, RV635_9590, RV635) +CHIPSET(0x9591, RV635_9591, RV635) +CHIPSET(0x9593, RV635_9593, RV635) +CHIPSET(0x9595, RV635_9595, RV635) +CHIPSET(0x9596, RV635_9596, RV635) +CHIPSET(0x9597, RV635_9597, RV635) +CHIPSET(0x9598, RV635_9598, RV635) +CHIPSET(0x9599, RV635_9599, RV635) +CHIPSET(0x959B, RV635_959B, RV635) + +CHIPSET(0x9610, RS780_9610, RS780) +CHIPSET(0x9611, RS780_9611, RS780) +CHIPSET(0x9612, RS780_9612, RS780) +CHIPSET(0x9613, RS780_9613, RS780) +CHIPSET(0x9614, RS780_9614, RS780) +CHIPSET(0x9615, RS780_9615, RS780) +CHIPSET(0x9616, RS780_9616, RS780) + +CHIPSET(0x9710, RS880_9710, RS880) +CHIPSET(0x9711, RS880_9711, RS880) +CHIPSET(0x9712, RS880_9712, RS880) +CHIPSET(0x9713, RS880_9713, RS880) +CHIPSET(0x9714, RS880_9714, RS880) +CHIPSET(0x9715, RS880_9715, RS880) + +CHIPSET(0x9440, RV770_9440, RV770) +CHIPSET(0x9441, RV770_9441, RV770) +CHIPSET(0x9442, RV770_9442, RV770) +CHIPSET(0x9443, RV770_9443, RV770) +CHIPSET(0x9444, RV770_9444, RV770) +CHIPSET(0x9446, RV770_9446, RV770) +CHIPSET(0x944A, RV770_944A, RV770) +CHIPSET(0x944B, RV770_944B, RV770) +CHIPSET(0x944C, RV770_944C, RV770) +CHIPSET(0x944E, RV770_944E, RV770) +CHIPSET(0x9450, RV770_9450, RV770) +CHIPSET(0x9452, RV770_9452, RV770) +CHIPSET(0x9456, RV770_9456, RV770) +CHIPSET(0x945A, RV770_945A, RV770) +CHIPSET(0x945B, RV770_945B, RV770) +CHIPSET(0x945E, RV770_945E, RV770) +CHIPSET(0x9460, RV790_9460, RV770) +CHIPSET(0x9462, RV790_9462, RV770) +CHIPSET(0x946A, RV770_946A, RV770) +CHIPSET(0x946B, RV770_946B, RV770) +CHIPSET(0x947A, RV770_947A, RV770) +CHIPSET(0x947B, RV770_947B, RV770) + +CHIPSET(0x9480, RV730_9480, RV730) +CHIPSET(0x9487, RV730_9487, RV730) +CHIPSET(0x9488, RV730_9488, RV730) +CHIPSET(0x9489, RV730_9489, RV730) +CHIPSET(0x948A, RV730_948A, RV730) +CHIPSET(0x948F, RV730_948F, RV730) +CHIPSET(0x9490, RV730_9490, RV730) +CHIPSET(0x9491, RV730_9491, RV730) +CHIPSET(0x9495, RV730_9495, RV730) +CHIPSET(0x9498, RV730_9498, RV730) +CHIPSET(0x949C, RV730_949C, RV730) +CHIPSET(0x949E, RV730_949E, RV730) +CHIPSET(0x949F, RV730_949F, RV730) + +CHIPSET(0x9540, RV710_9540, RV710) +CHIPSET(0x9541, RV710_9541, RV710) +CHIPSET(0x9542, RV710_9542, RV710) +CHIPSET(0x954E, RV710_954E, RV710) +CHIPSET(0x954F, RV710_954F, RV710) +CHIPSET(0x9552, RV710_9552, RV710) +CHIPSET(0x9553, RV710_9553, RV710) +CHIPSET(0x9555, RV710_9555, RV710) +CHIPSET(0x9557, RV710_9557, RV710) +CHIPSET(0x955F, RV710_955F, RV710) + +CHIPSET(0x94A0, RV740_94A0, RV740) +CHIPSET(0x94A1, RV740_94A1, RV740) +CHIPSET(0x94A3, RV740_94A3, RV740) +CHIPSET(0x94B1, RV740_94B1, RV740) +CHIPSET(0x94B3, RV740_94B3, RV740) +CHIPSET(0x94B4, RV740_94B4, RV740) +CHIPSET(0x94B5, RV740_94B5, RV740) +CHIPSET(0x94B9, RV740_94B9, RV740) + +CHIPSET(0x68E0, CEDAR_68E0, CEDAR) +CHIPSET(0x68E1, CEDAR_68E1, CEDAR) +CHIPSET(0x68E4, CEDAR_68E4, CEDAR) +CHIPSET(0x68E5, CEDAR_68E5, CEDAR) +CHIPSET(0x68E8, CEDAR_68E8, CEDAR) +CHIPSET(0x68E9, CEDAR_68E9, CEDAR) +CHIPSET(0x68F1, CEDAR_68F1, CEDAR) +CHIPSET(0x68F2, CEDAR_68F2, CEDAR) +CHIPSET(0x68F8, CEDAR_68F8, CEDAR) +CHIPSET(0x68F9, CEDAR_68F9, CEDAR) +CHIPSET(0x68FA, CEDAR_68FA, CEDAR) +CHIPSET(0x68FE, CEDAR_68FE, CEDAR) + +CHIPSET(0x68C0, REDWOOD_68C0, REDWOOD) +CHIPSET(0x68C1, REDWOOD_68C1, REDWOOD) +CHIPSET(0x68C7, REDWOOD_68C7, REDWOOD) +CHIPSET(0x68C8, REDWOOD_68C8, REDWOOD) +CHIPSET(0x68C9, REDWOOD_68C9, REDWOOD) +CHIPSET(0x68D8, REDWOOD_68D8, REDWOOD) +CHIPSET(0x68D9, REDWOOD_68D9, REDWOOD) +CHIPSET(0x68DA, REDWOOD_68DA, REDWOOD) +CHIPSET(0x68DE, REDWOOD_68DE, REDWOOD) + +CHIPSET(0x68A0, JUNIPER_68A0, JUNIPER) +CHIPSET(0x68A1, JUNIPER_68A1, JUNIPER) +CHIPSET(0x68A8, JUNIPER_68A8, JUNIPER) +CHIPSET(0x68A9, JUNIPER_68A9, JUNIPER) +CHIPSET(0x68B0, JUNIPER_68B0, JUNIPER) +CHIPSET(0x68B8, JUNIPER_68B8, JUNIPER) +CHIPSET(0x68B9, JUNIPER_68B9, JUNIPER) +CHIPSET(0x68BA, JUNIPER_68BA, JUNIPER) +CHIPSET(0x68BE, JUNIPER_68BE, JUNIPER) +CHIPSET(0x68BF, JUNIPER_68BF, JUNIPER) + +CHIPSET(0x6880, CYPRESS_6880, CYPRESS) +CHIPSET(0x6888, CYPRESS_6888, CYPRESS) +CHIPSET(0x6889, CYPRESS_6889, CYPRESS) +CHIPSET(0x688A, CYPRESS_688A, CYPRESS) +CHIPSET(0x688C, CYPRESS_688C, CYPRESS) +CHIPSET(0x688D, CYPRESS_688D, CYPRESS) +CHIPSET(0x6898, CYPRESS_6898, CYPRESS) +CHIPSET(0x6899, CYPRESS_6899, CYPRESS) +CHIPSET(0x689B, CYPRESS_689B, CYPRESS) +CHIPSET(0x689E, CYPRESS_689E, CYPRESS) + +CHIPSET(0x689C, HEMLOCK_689C, HEMLOCK) +CHIPSET(0x689D, HEMLOCK_689D, HEMLOCK) + +CHIPSET(0x9802, PALM_9802, PALM) +CHIPSET(0x9803, PALM_9803, PALM) +CHIPSET(0x9804, PALM_9804, PALM) +CHIPSET(0x9805, PALM_9805, PALM) +CHIPSET(0x9806, PALM_9806, PALM) +CHIPSET(0x9807, PALM_9807, PALM) +CHIPSET(0x9808, PALM_9808, PALM) +CHIPSET(0x9809, PALM_9809, PALM) +CHIPSET(0x980A, PALM_980A, PALM) + +CHIPSET(0x9640, SUMO_9640, SUMO) +CHIPSET(0x9641, SUMO_9641, SUMO) +CHIPSET(0x9642, SUMO2_9642, SUMO2) +CHIPSET(0x9643, SUMO2_9643, SUMO2) +CHIPSET(0x9644, SUMO2_9644, SUMO2) +CHIPSET(0x9645, SUMO2_9645, SUMO2) +CHIPSET(0x9647, SUMO_9647, SUMO) +CHIPSET(0x9648, SUMO_9648, SUMO) +CHIPSET(0x9649, SUMO2_9649, SUMO2) +CHIPSET(0x964a, SUMO_964A, SUMO) +CHIPSET(0x964b, SUMO_964B, SUMO) +CHIPSET(0x964c, SUMO_964C, SUMO) +CHIPSET(0x964e, SUMO_964E, SUMO) +CHIPSET(0x964f, SUMO_964F, SUMO) + +CHIPSET(0x6700, CAYMAN_6700, CAYMAN) +CHIPSET(0x6701, CAYMAN_6701, CAYMAN) +CHIPSET(0x6702, CAYMAN_6702, CAYMAN) +CHIPSET(0x6703, CAYMAN_6703, CAYMAN) +CHIPSET(0x6704, CAYMAN_6704, CAYMAN) +CHIPSET(0x6705, CAYMAN_6705, CAYMAN) +CHIPSET(0x6706, CAYMAN_6706, CAYMAN) +CHIPSET(0x6707, CAYMAN_6707, CAYMAN) +CHIPSET(0x6708, CAYMAN_6708, CAYMAN) +CHIPSET(0x6709, CAYMAN_6709, CAYMAN) +CHIPSET(0x6718, CAYMAN_6718, CAYMAN) +CHIPSET(0x6719, CAYMAN_6719, CAYMAN) +CHIPSET(0x671C, CAYMAN_671C, CAYMAN) +CHIPSET(0x671D, CAYMAN_671D, CAYMAN) +CHIPSET(0x671F, CAYMAN_671F, CAYMAN) + +CHIPSET(0x6720, BARTS_6720, BARTS) +CHIPSET(0x6721, BARTS_6721, BARTS) +CHIPSET(0x6722, BARTS_6722, BARTS) +CHIPSET(0x6723, BARTS_6723, BARTS) +CHIPSET(0x6724, BARTS_6724, BARTS) +CHIPSET(0x6725, BARTS_6725, BARTS) +CHIPSET(0x6726, BARTS_6726, BARTS) +CHIPSET(0x6727, BARTS_6727, BARTS) +CHIPSET(0x6728, BARTS_6728, BARTS) +CHIPSET(0x6729, BARTS_6729, BARTS) +CHIPSET(0x6738, BARTS_6738, BARTS) +CHIPSET(0x6739, BARTS_6739, BARTS) +CHIPSET(0x673E, BARTS_673E, BARTS) + +CHIPSET(0x6740, TURKS_6740, TURKS) +CHIPSET(0x6741, TURKS_6741, TURKS) +CHIPSET(0x6742, TURKS_6742, TURKS) +CHIPSET(0x6743, TURKS_6743, TURKS) +CHIPSET(0x6744, TURKS_6744, TURKS) +CHIPSET(0x6745, TURKS_6745, TURKS) +CHIPSET(0x6746, TURKS_6746, TURKS) +CHIPSET(0x6747, TURKS_6747, TURKS) +CHIPSET(0x6748, TURKS_6748, TURKS) +CHIPSET(0x6749, TURKS_6749, TURKS) +CHIPSET(0x674A, TURKS_674A, TURKS) +CHIPSET(0x6750, TURKS_6750, TURKS) +CHIPSET(0x6751, TURKS_6751, TURKS) +CHIPSET(0x6758, TURKS_6758, TURKS) +CHIPSET(0x6759, TURKS_6759, TURKS) +CHIPSET(0x675B, TURKS_675B, TURKS) +CHIPSET(0x675D, TURKS_675D, TURKS) +CHIPSET(0x675F, TURKS_675F, TURKS) +CHIPSET(0x6840, TURKS_6840, TURKS) +CHIPSET(0x6841, TURKS_6841, TURKS) +CHIPSET(0x6842, TURKS_6842, TURKS) +CHIPSET(0x6843, TURKS_6843, TURKS) +CHIPSET(0x6849, TURKS_6849, TURKS) +CHIPSET(0x6850, TURKS_6850, TURKS) +CHIPSET(0x6858, TURKS_6858, TURKS) +CHIPSET(0x6859, TURKS_6859, TURKS) + +CHIPSET(0x6760, CAICOS_6760, CAICOS) +CHIPSET(0x6761, CAICOS_6761, CAICOS) +CHIPSET(0x6762, CAICOS_6762, CAICOS) +CHIPSET(0x6763, CAICOS_6763, CAICOS) +CHIPSET(0x6764, CAICOS_6764, CAICOS) +CHIPSET(0x6765, CAICOS_6765, CAICOS) +CHIPSET(0x6766, CAICOS_6766, CAICOS) +CHIPSET(0x6767, CAICOS_6767, CAICOS) +CHIPSET(0x6768, CAICOS_6768, CAICOS) +CHIPSET(0x6770, CAICOS_6770, CAICOS) +CHIPSET(0x6771, CAICOS_6771, CAICOS) +CHIPSET(0x6772, CAICOS_6772, CAICOS) +CHIPSET(0x6778, CAICOS_6778, CAICOS) +CHIPSET(0x6779, CAICOS_6779, CAICOS) +CHIPSET(0x677B, CAICOS_677B, CAICOS) + +CHIPSET(0x9900, ARUBA_9900, ARUBA) +CHIPSET(0x9901, ARUBA_9901, ARUBA) +CHIPSET(0x9903, ARUBA_9903, ARUBA) +CHIPSET(0x9904, ARUBA_9904, ARUBA) +CHIPSET(0x9905, ARUBA_9905, ARUBA) +CHIPSET(0x9906, ARUBA_9906, ARUBA) +CHIPSET(0x9907, ARUBA_9907, ARUBA) +CHIPSET(0x9908, ARUBA_9908, ARUBA) +CHIPSET(0x9909, ARUBA_9909, ARUBA) +CHIPSET(0x990A, ARUBA_990A, ARUBA) +CHIPSET(0x990B, ARUBA_990B, ARUBA) +CHIPSET(0x990C, ARUBA_990C, ARUBA) +CHIPSET(0x990D, ARUBA_990D, ARUBA) +CHIPSET(0x990E, ARUBA_990E, ARUBA) +CHIPSET(0x990F, ARUBA_990F, ARUBA) +CHIPSET(0x9910, ARUBA_9910, ARUBA) +CHIPSET(0x9913, ARUBA_9913, ARUBA) +CHIPSET(0x9917, ARUBA_9917, ARUBA) +CHIPSET(0x9918, ARUBA_9918, ARUBA) +CHIPSET(0x9919, ARUBA_9919, ARUBA) +CHIPSET(0x9990, ARUBA_9990, ARUBA) +CHIPSET(0x9991, ARUBA_9991, ARUBA) +CHIPSET(0x9992, ARUBA_9992, ARUBA) +CHIPSET(0x9993, ARUBA_9993, ARUBA) +CHIPSET(0x9994, ARUBA_9994, ARUBA) +CHIPSET(0x9995, ARUBA_9995, ARUBA) +CHIPSET(0x9996, ARUBA_9996, ARUBA) +CHIPSET(0x9997, ARUBA_9997, ARUBA) +CHIPSET(0x9998, ARUBA_9998, ARUBA) +CHIPSET(0x9999, ARUBA_9999, ARUBA) +CHIPSET(0x999A, ARUBA_999A, ARUBA) +CHIPSET(0x999B, ARUBA_999B, ARUBA) +CHIPSET(0x999C, ARUBA_999C, ARUBA) +CHIPSET(0x999D, ARUBA_999D, ARUBA) +CHIPSET(0x99A0, ARUBA_99A0, ARUBA) +CHIPSET(0x99A2, ARUBA_99A2, ARUBA) +CHIPSET(0x99A4, ARUBA_99A4, ARUBA) diff --git a/hw/xfree86/dri2/pci_ids/radeon_pci_ids.h b/hw/xfree86/dri2/pci_ids/radeon_pci_ids.h new file mode 100644 index 000000000..a9efc767d --- /dev/null +++ b/hw/xfree86/dri2/pci_ids/radeon_pci_ids.h @@ -0,0 +1,23 @@ +CHIPSET(0x4C57, RADEON_LW, RV200) +CHIPSET(0x4C58, RADEON_LX, RV200) +CHIPSET(0x4C59, RADEON_LY, RV100) +CHIPSET(0x4C5A, RADEON_LZ, RV100) +CHIPSET(0x5144, RADEON_QD, R100) +CHIPSET(0x5145, RADEON_QE, R100) +CHIPSET(0x5146, RADEON_QF, R100) +CHIPSET(0x5147, RADEON_QG, R100) +CHIPSET(0x5159, RADEON_QY, RV100) +CHIPSET(0x515A, RADEON_QZ, RV100) + +CHIPSET(0x5157, RV200_QW, RV200) +CHIPSET(0x5158, RV200_QX, RV200) + +CHIPSET(0x515E, RN50_515E, UNKNOWN) +CHIPSET(0x5969, RN50_5969, UNKNOWN) + +CHIPSET(0x4136, RS100_4136, RS100) +CHIPSET(0x4336, RS100_4336, RS100) +CHIPSET(0x4137, RS200_4137, RS200) +CHIPSET(0x4337, RS200_4337, RS200) +CHIPSET(0x4237, RS250_4237, RS200) +CHIPSET(0x4437, RS250_4437, RS200) diff --git a/hw/xfree86/dri2/pci_ids/radeonsi_pci_ids.h b/hw/xfree86/dri2/pci_ids/radeonsi_pci_ids.h new file mode 100644 index 000000000..571e8633f --- /dev/null +++ b/hw/xfree86/dri2/pci_ids/radeonsi_pci_ids.h @@ -0,0 +1,157 @@ +CHIPSET(0x6780, TAHITI_6780, TAHITI) +CHIPSET(0x6784, TAHITI_6784, TAHITI) +CHIPSET(0x6788, TAHITI_6788, TAHITI) +CHIPSET(0x678A, TAHITI_678A, TAHITI) +CHIPSET(0x6790, TAHITI_6790, TAHITI) +CHIPSET(0x6791, TAHITI_6791, TAHITI) +CHIPSET(0x6792, TAHITI_6792, TAHITI) +CHIPSET(0x6798, TAHITI_6798, TAHITI) +CHIPSET(0x6799, TAHITI_6799, TAHITI) +CHIPSET(0x679A, TAHITI_679A, TAHITI) +CHIPSET(0x679B, TAHITI_679B, TAHITI) +CHIPSET(0x679E, TAHITI_679E, TAHITI) +CHIPSET(0x679F, TAHITI_679F, TAHITI) + +CHIPSET(0x6800, PITCAIRN_6800, PITCAIRN) +CHIPSET(0x6801, PITCAIRN_6801, PITCAIRN) +CHIPSET(0x6802, PITCAIRN_6802, PITCAIRN) +CHIPSET(0x6806, PITCAIRN_6806, PITCAIRN) +CHIPSET(0x6808, PITCAIRN_6808, PITCAIRN) +CHIPSET(0x6809, PITCAIRN_6809, PITCAIRN) +CHIPSET(0x6810, PITCAIRN_6810, PITCAIRN) +CHIPSET(0x6811, PITCAIRN_6811, PITCAIRN) +CHIPSET(0x6816, PITCAIRN_6816, PITCAIRN) +CHIPSET(0x6817, PITCAIRN_6817, PITCAIRN) +CHIPSET(0x6818, PITCAIRN_6818, PITCAIRN) +CHIPSET(0x6819, PITCAIRN_6819, PITCAIRN) +CHIPSET(0x684C, PITCAIRN_684C, PITCAIRN) + +CHIPSET(0x6820, VERDE_6820, VERDE) +CHIPSET(0x6821, VERDE_6821, VERDE) +CHIPSET(0x6822, VERDE_6822, VERDE) +CHIPSET(0x6823, VERDE_6823, VERDE) +CHIPSET(0x6824, VERDE_6824, VERDE) +CHIPSET(0x6825, VERDE_6825, VERDE) +CHIPSET(0x6826, VERDE_6826, VERDE) +CHIPSET(0x6827, VERDE_6827, VERDE) +CHIPSET(0x6828, VERDE_6828, VERDE) +CHIPSET(0x6829, VERDE_6829, VERDE) +CHIPSET(0x682A, VERDE_682A, VERDE) +CHIPSET(0x682B, VERDE_682B, VERDE) +CHIPSET(0x682C, VERDE_682C, VERDE) +CHIPSET(0x682D, VERDE_682D, VERDE) +CHIPSET(0x682F, VERDE_682F, VERDE) +CHIPSET(0x6830, VERDE_6830, VERDE) +CHIPSET(0x6831, VERDE_6831, VERDE) +CHIPSET(0x6835, VERDE_6835, VERDE) +CHIPSET(0x6837, VERDE_6837, VERDE) +CHIPSET(0x6838, VERDE_6838, VERDE) +CHIPSET(0x6839, VERDE_6839, VERDE) +CHIPSET(0x683B, VERDE_683B, VERDE) +CHIPSET(0x683D, VERDE_683D, VERDE) +CHIPSET(0x683F, VERDE_683F, VERDE) + +CHIPSET(0x6600, OLAND_6600, OLAND) +CHIPSET(0x6601, OLAND_6601, OLAND) +CHIPSET(0x6602, OLAND_6602, OLAND) +CHIPSET(0x6603, OLAND_6603, OLAND) +CHIPSET(0x6604, OLAND_6604, OLAND) +CHIPSET(0x6605, OLAND_6605, OLAND) +CHIPSET(0x6606, OLAND_6606, OLAND) +CHIPSET(0x6607, OLAND_6607, OLAND) +CHIPSET(0x6608, OLAND_6608, OLAND) +CHIPSET(0x6610, OLAND_6610, OLAND) +CHIPSET(0x6611, OLAND_6611, OLAND) +CHIPSET(0x6613, OLAND_6613, OLAND) +CHIPSET(0x6620, OLAND_6620, OLAND) +CHIPSET(0x6621, OLAND_6621, OLAND) +CHIPSET(0x6623, OLAND_6623, OLAND) +CHIPSET(0x6631, OLAND_6631, OLAND) + +CHIPSET(0x6660, HAINAN_6660, HAINAN) +CHIPSET(0x6663, HAINAN_6663, HAINAN) +CHIPSET(0x6664, HAINAN_6664, HAINAN) +CHIPSET(0x6665, HAINAN_6665, HAINAN) +CHIPSET(0x6667, HAINAN_6667, HAINAN) +CHIPSET(0x666F, HAINAN_666F, HAINAN) + +CHIPSET(0x6640, BONAIRE_6640, BONAIRE) +CHIPSET(0x6641, BONAIRE_6641, BONAIRE) +CHIPSET(0x6646, BONAIRE_6646, BONAIRE) +CHIPSET(0x6647, BONAIRE_6647, BONAIRE) +CHIPSET(0x6649, BONAIRE_6649, BONAIRE) +CHIPSET(0x6650, BONAIRE_6650, BONAIRE) +CHIPSET(0x6651, BONAIRE_6651, BONAIRE) +CHIPSET(0x6658, BONAIRE_6658, BONAIRE) +CHIPSET(0x665C, BONAIRE_665C, BONAIRE) +CHIPSET(0x665D, BONAIRE_665D, BONAIRE) + +CHIPSET(0x9830, KABINI_9830, KABINI) +CHIPSET(0x9831, KABINI_9831, KABINI) +CHIPSET(0x9832, KABINI_9832, KABINI) +CHIPSET(0x9833, KABINI_9833, KABINI) +CHIPSET(0x9834, KABINI_9834, KABINI) +CHIPSET(0x9835, KABINI_9835, KABINI) +CHIPSET(0x9836, KABINI_9836, KABINI) +CHIPSET(0x9837, KABINI_9837, KABINI) +CHIPSET(0x9838, KABINI_9838, KABINI) +CHIPSET(0x9839, KABINI_9839, KABINI) +CHIPSET(0x983A, KABINI_983A, KABINI) +CHIPSET(0x983B, KABINI_983B, KABINI) +CHIPSET(0x983C, KABINI_983C, KABINI) +CHIPSET(0x983D, KABINI_983D, KABINI) +CHIPSET(0x983E, KABINI_983E, KABINI) +CHIPSET(0x983F, KABINI_983F, KABINI) + +CHIPSET(0x9850, MULLINS_9850, MULLINS) +CHIPSET(0x9851, MULLINS_9851, MULLINS) +CHIPSET(0x9852, MULLINS_9852, MULLINS) +CHIPSET(0x9853, MULLINS_9853, MULLINS) +CHIPSET(0x9854, MULLINS_9854, MULLINS) +CHIPSET(0x9855, MULLINS_9855, MULLINS) +CHIPSET(0x9856, MULLINS_9856, MULLINS) +CHIPSET(0x9857, MULLINS_9857, MULLINS) +CHIPSET(0x9858, MULLINS_9858, MULLINS) +CHIPSET(0x9859, MULLINS_9859, MULLINS) +CHIPSET(0x985A, MULLINS_985A, MULLINS) +CHIPSET(0x985B, MULLINS_985B, MULLINS) +CHIPSET(0x985C, MULLINS_985C, MULLINS) +CHIPSET(0x985D, MULLINS_985D, MULLINS) +CHIPSET(0x985E, MULLINS_985E, MULLINS) +CHIPSET(0x985F, MULLINS_985F, MULLINS) + +CHIPSET(0x1304, KAVERI_1304, KAVERI) +CHIPSET(0x1305, KAVERI_1305, KAVERI) +CHIPSET(0x1306, KAVERI_1306, KAVERI) +CHIPSET(0x1307, KAVERI_1307, KAVERI) +CHIPSET(0x1309, KAVERI_1309, KAVERI) +CHIPSET(0x130A, KAVERI_130A, KAVERI) +CHIPSET(0x130B, KAVERI_130B, KAVERI) +CHIPSET(0x130C, KAVERI_130C, KAVERI) +CHIPSET(0x130D, KAVERI_130D, KAVERI) +CHIPSET(0x130E, KAVERI_130E, KAVERI) +CHIPSET(0x130F, KAVERI_130F, KAVERI) +CHIPSET(0x1310, KAVERI_1310, KAVERI) +CHIPSET(0x1311, KAVERI_1311, KAVERI) +CHIPSET(0x1312, KAVERI_1312, KAVERI) +CHIPSET(0x1313, KAVERI_1313, KAVERI) +CHIPSET(0x1315, KAVERI_1315, KAVERI) +CHIPSET(0x1316, KAVERI_1316, KAVERI) +CHIPSET(0x1317, KAVERI_1317, KAVERI) +CHIPSET(0x1318, KAVERI_1318, KAVERI) +CHIPSET(0x131B, KAVERI_131B, KAVERI) +CHIPSET(0x131C, KAVERI_131C, KAVERI) +CHIPSET(0x131D, KAVERI_131D, KAVERI) + +CHIPSET(0x67A0, HAWAII_67A0, HAWAII) +CHIPSET(0x67A1, HAWAII_67A1, HAWAII) +CHIPSET(0x67A2, HAWAII_67A2, HAWAII) +CHIPSET(0x67A8, HAWAII_67A8, HAWAII) +CHIPSET(0x67A9, HAWAII_67A9, HAWAII) +CHIPSET(0x67AA, HAWAII_67AA, HAWAII) +CHIPSET(0x67B0, HAWAII_67B0, HAWAII) +CHIPSET(0x67B1, HAWAII_67B1, HAWAII) +CHIPSET(0x67B8, HAWAII_67B8, HAWAII) +CHIPSET(0x67B9, HAWAII_67B9, HAWAII) +CHIPSET(0x67BA, HAWAII_67BA, HAWAII) +CHIPSET(0x67BE, HAWAII_67BE, HAWAII) diff --git a/hw/xfree86/dri2/pci_ids/vmwgfx_pci_ids.h b/hw/xfree86/dri2/pci_ids/vmwgfx_pci_ids.h new file mode 100644 index 000000000..124d75b72 --- /dev/null +++ b/hw/xfree86/dri2/pci_ids/vmwgfx_pci_ids.h @@ -0,0 +1 @@ +CHIPSET(0x0405, SVGAII, SVGAII) diff --git a/hw/xfree86/drivers/modesetting/Makefile.am b/hw/xfree86/drivers/modesetting/Makefile.am index e6834e283..5b08600c1 100644 --- a/hw/xfree86/drivers/modesetting/Makefile.am +++ b/hw/xfree86/drivers/modesetting/Makefile.am @@ -30,6 +30,7 @@ AM_CPPFLAGS = \ $(XORG_INCS) \ -I$(top_srcdir)/glamor \ -I$(srcdir)/../../ddc \ + -I$(srcdir)/../../dri2 \ -I$(srcdir)/../../i2c \ -I$(srcdir)/../../modes \ -I$(srcdir)/../../parser \ @@ -42,10 +43,13 @@ modesetting_drv_la_LIBADD = $(UDEV_LIBS) $(DRM_LIBS) modesetting_drv_ladir = @moduledir@/drivers modesetting_drv_la_SOURCES = \ + dri2.c \ driver.c \ driver.h \ drmmode_display.c \ - drmmode_display.h + drmmode_display.h \ + vblank.c \ + $(NULL) drivermandir = $(DRIVER_MAN_DIR) driverman_PRE = modesetting.man diff --git a/hw/xfree86/drivers/modesetting/dri2.c b/hw/xfree86/drivers/modesetting/dri2.c new file mode 100644 index 000000000..6c88060b0 --- /dev/null +++ b/hw/xfree86/drivers/modesetting/dri2.c @@ -0,0 +1,863 @@ +/* + * Copyright © 2013 Intel Corporation + * Copyright © 2014 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * @file dri2.c + * + * Implements generic support for DRI2 on KMS, using glamor pixmaps + * for color buffer management (no support for other aux buffers), and + * the DRM vblank ioctls. + * + * This doesn't implement pageflipping yet. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include "dix-config.h" +#endif + +#include +#include "list.h" +#include "xf86.h" +#include "driver.h" +#include "dri2.h" + +#ifdef GLAMOR +#define GLAMOR_FOR_XORG 1 +#include "glamor.h" + +enum ms_dri2_frame_event_type { + MS_DRI2_QUEUE_SWAP, + MS_DRI2_WAIT_MSC, +}; + +typedef struct ms_dri2_frame_event { + ScreenPtr screen; + + DrawablePtr drawable; + ClientPtr client; + enum ms_dri2_frame_event_type type; + int frame; + xf86CrtcPtr crtc; + + struct xorg_list drawable_resource, client_resource; + + /* for swaps & flips only */ + DRI2SwapEventPtr event_complete; + void *event_data; + DRI2BufferPtr front; + DRI2BufferPtr back; +} ms_dri2_frame_event_rec, *ms_dri2_frame_event_ptr; + +typedef struct { + int refcnt; + PixmapPtr pixmap; +} ms_dri2_buffer_private_rec, *ms_dri2_buffer_private_ptr; + +static DevPrivateKeyRec ms_dri2_client_key; +static RESTYPE frame_event_client_type, frame_event_drawable_type; +static int ms_dri2_server_generation; + +struct ms_dri2_resource { + XID id; + RESTYPE type; + struct xorg_list list; +}; + +static struct ms_dri2_resource * +ms_get_resource(XID id, RESTYPE type) +{ + struct ms_dri2_resource *resource; + void *ptr; + + ptr = NULL; + dixLookupResourceByType(&ptr, id, type, NULL, DixWriteAccess); + if (ptr) + return ptr; + + resource = malloc(sizeof(*resource)); + if (resource == NULL) + return NULL; + + if (!AddResource(id, type, resource)) { + free(resource); + return NULL; + } + + resource->id = id; + resource->type = type; + xorg_list_init(&resource->list); + return resource; +} + +static inline PixmapPtr +get_drawable_pixmap(DrawablePtr drawable) +{ + ScreenPtr screen = drawable->pScreen; + + if (drawable->type == DRAWABLE_PIXMAP) + return (PixmapPtr) drawable; + else + return screen->GetWindowPixmap((WindowPtr) drawable); +} + +static PixmapPtr +get_front_buffer(DrawablePtr drawable) +{ + PixmapPtr pixmap; + + pixmap = get_drawable_pixmap(drawable); + pixmap->refcnt++; + + return pixmap; +} + +static DRI2Buffer2Ptr +ms_dri2_create_buffer(DrawablePtr drawable, unsigned int attachment, + unsigned int format) +{ + ScreenPtr screen = drawable->pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + DRI2Buffer2Ptr buffer; + PixmapPtr pixmap; + uint32_t size; + uint16_t pitch; + ms_dri2_buffer_private_ptr private; + + buffer = calloc(1, sizeof *buffer); + if (buffer == NULL) + return NULL; + + private = calloc(1, sizeof(*private)); + if (private == NULL) { + free(buffer); + return NULL; + } + + pixmap = NULL; + if (attachment == DRI2BufferFrontLeft) + pixmap = get_front_buffer(drawable); + + if (pixmap == NULL) { + int pixmap_width = drawable->width; + int pixmap_height = drawable->height; + int pixmap_cpp = (format != 0) ? format : drawable->depth; + + /* Assume that non-color-buffers require special + * device-specific handling. Mesa currently makes no requests + * for non-color aux buffers. + */ + switch (attachment) { + case DRI2BufferAccum: + case DRI2BufferBackLeft: + case DRI2BufferBackRight: + case DRI2BufferFakeFrontLeft: + case DRI2BufferFakeFrontRight: + case DRI2BufferFrontLeft: + case DRI2BufferFrontRight: + break; + + case DRI2BufferStencil: + case DRI2BufferDepth: + case DRI2BufferDepthStencil: + case DRI2BufferHiz: + default: + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Request for DRI2 buffer attachment %d unsupported\n", + attachment); + free(private); + free(buffer); + return NULL; + } + + pixmap = screen->CreatePixmap(screen, + pixmap_width, + pixmap_height, + pixmap_cpp, + 0); + if (pixmap == NULL) { + if (pixmap) + screen->DestroyPixmap(pixmap); + free(private); + free(buffer); + return NULL; + } + } + + buffer->attachment = attachment; + buffer->cpp = pixmap->drawable.bitsPerPixel / 8; + buffer->format = format; + /* The buffer's flags field is unused by the client drivers in + * Mesa currently. + */ + buffer->flags = 0; + + buffer->name = glamor_name_from_pixmap(pixmap, &pitch, &size); + buffer->pitch = pitch; + if (buffer->name == -1) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to get DRI2 name for pixmap\n"); + screen->DestroyPixmap(pixmap); + free(private); + free(buffer); + return NULL; + } + + buffer->driverPrivate = private; + private->refcnt = 1; + private->pixmap = pixmap; + + return buffer; +} + +static void +ms_dri2_reference_buffer(DRI2Buffer2Ptr buffer) +{ + if (buffer) { + ms_dri2_buffer_private_ptr private = buffer->driverPrivate; + private->refcnt++; + } +} + +static void ms_dri2_destroy_buffer(DrawablePtr drawable, DRI2Buffer2Ptr buffer) +{ + if (!buffer) + return; + + if (buffer->driverPrivate) { + ms_dri2_buffer_private_ptr private = buffer->driverPrivate; + if (--private->refcnt == 0) { + ScreenPtr screen = private->pixmap->drawable.pScreen; + screen->DestroyPixmap(private->pixmap); + free(private); + free(buffer); + } + } else { + free(buffer); + } +} + +static void +ms_dri2_copy_region(DrawablePtr drawable, RegionPtr pRegion, + DRI2BufferPtr destBuffer, DRI2BufferPtr sourceBuffer) +{ + ms_dri2_buffer_private_ptr src_priv = sourceBuffer->driverPrivate; + ms_dri2_buffer_private_ptr dst_priv = destBuffer->driverPrivate; + PixmapPtr src_pixmap = src_priv->pixmap; + PixmapPtr dst_pixmap = dst_priv->pixmap; + ScreenPtr screen = drawable->pScreen; + DrawablePtr src = (sourceBuffer->attachment == DRI2BufferFrontLeft) + ? drawable : &src_pixmap->drawable; + DrawablePtr dst = (destBuffer->attachment == DRI2BufferFrontLeft) + ? drawable : &dst_pixmap->drawable; + RegionPtr pCopyClip; + GCPtr gc; + + gc = GetScratchGC(dst->depth, screen); + if (!gc) + return; + + pCopyClip = REGION_CREATE(screen, NULL, 0); + REGION_COPY(screen, pCopyClip, pRegion); + (*gc->funcs->ChangeClip) (gc, CT_REGION, pCopyClip, 0); + ValidateGC(dst, gc); + + /* It's important that this copy gets submitted before the direct + * rendering client submits rendering for the next frame, but we + * don't actually need to submit right now. The client will wait + * for the DRI2CopyRegion reply or the swap buffer event before + * rendering, and we'll hit the flush callback chain before those + * messages are sent. We submit our batch buffers from the flush + * callback chain so we know that will happen before the client + * tries to render again. + */ + gc->ops->CopyArea(src, dst, gc, + 0, 0, + drawable->width, drawable->height, + 0, 0); + + FreeScratchGC(gc); +} + +static uint64_t +gettime_us(void) +{ + struct timespec tv; + + if (clock_gettime(CLOCK_MONOTONIC, &tv)) + return 0; + + return (uint64_t)tv.tv_sec * 1000000 + tv.tv_nsec / 1000; +} + +/** + * Get current frame count and frame count timestamp, based on drawable's + * crtc. + */ +static int +ms_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) +{ + int ret; + xf86CrtcPtr crtc = ms_dri2_crtc_covering_drawable(draw); + + /* Drawable not displayed, make up a *monotonic* value */ + if (crtc == NULL) { + *ust = gettime_us(); + *msc = 0; + return TRUE; + } + + ret = ms_get_crtc_ust_msc(crtc, ust, msc); + + if (ret) + return FALSE; + + return TRUE; +} + +static XID +get_client_id(ClientPtr client) +{ + XID *ptr = dixGetPrivateAddr(&client->devPrivates, &ms_dri2_client_key); + if (*ptr == 0) + *ptr = FakeClientID(client->index); + return *ptr; +} + +/* + * Hook this frame event into the server resource + * database so we can clean it up if the drawable or + * client exits while the swap is pending + */ +static Bool +ms_dri2_add_frame_event(ms_dri2_frame_event_ptr info) +{ + struct ms_dri2_resource *resource; + + resource = ms_get_resource(get_client_id(info->client), + frame_event_client_type); + if (resource == NULL) + return FALSE; + + xorg_list_add(&info->client_resource, &resource->list); + + resource = ms_get_resource(info->drawable->id, frame_event_drawable_type); + if (resource == NULL) { + xorg_list_del(&info->client_resource); + return FALSE; + } + + xorg_list_add(&info->drawable_resource, &resource->list); + + return TRUE; +} + +static void +ms_dri2_del_frame_event(ms_dri2_frame_event_rec *info) +{ + xorg_list_del(&info->client_resource); + xorg_list_del(&info->drawable_resource); + + if (info->front) + ms_dri2_destroy_buffer(NULL, info->front); + if (info->back) + ms_dri2_destroy_buffer(NULL, info->back); + + free(info); +} + +static void +ms_dri2_blit_swap(DrawablePtr drawable, + DRI2BufferPtr dst, + DRI2BufferPtr src) +{ + BoxRec box; + RegionRec region; + + box.x1 = 0; + box.y1 = 0; + box.x2 = drawable->width; + box.y2 = drawable->height; + REGION_INIT(pScreen, ®ion, &box, 0); + + ms_dri2_copy_region(drawable, ®ion, dst, src); +} + +static void +ms_dri2_frame_event_handler(uint64_t msc, + uint64_t usec, + void *data) +{ + ms_dri2_frame_event_ptr frame_info = data; + DrawablePtr drawable = frame_info->drawable; + ScreenPtr screen = frame_info->screen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + uint32_t tv_sec = usec / 1000000; + uint32_t tv_usec = usec % 1000000; + + if (!drawable) { + ms_dri2_del_frame_event(frame_info); + return; + } + + switch (frame_info->type) { + case MS_DRI2_QUEUE_SWAP: + ms_dri2_blit_swap(drawable, frame_info->front, frame_info->back); + DRI2SwapComplete(frame_info->client, drawable, msc, tv_sec, tv_usec, + DRI2_BLIT_COMPLETE, + frame_info->client ? frame_info->event_complete : NULL, + frame_info->event_data); + break; + + case MS_DRI2_WAIT_MSC: + if (frame_info->client) + DRI2WaitMSCComplete(frame_info->client, drawable, + msc, tv_sec, tv_usec); + break; + + default: + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "%s: unknown vblank event (type %d) received\n", __func__, + frame_info->type); + break; + } + + ms_dri2_del_frame_event(frame_info); +} + +static void +ms_dri2_frame_event_abort(void *data) +{ + ms_dri2_frame_event_ptr frame_info = data; + + ms_dri2_del_frame_event(frame_info); +} + +/** + * Request a DRM event when the requested conditions will be satisfied. + * + * We need to handle the event and ask the server to wake up the client when + * we receive it. + */ +static int +ms_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc, + CARD64 divisor, CARD64 remainder) +{ + ScreenPtr screen = draw->pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); + ms_dri2_frame_event_ptr wait_info; + drmVBlank vbl; + int ret; + xf86CrtcPtr crtc = ms_dri2_crtc_covering_drawable(draw); + drmmode_crtc_private_ptr drmmode_crtc; + CARD64 current_msc, current_ust, request_msc; + uint32_t seq; + + /* Drawable not visible, return immediately */ + if (!crtc) + goto out_complete; + drmmode_crtc = crtc->driver_private; + + wait_info = calloc(1, sizeof(*wait_info)); + if (!wait_info) + goto out_complete; + + wait_info->screen = screen; + wait_info->drawable = draw; + wait_info->client = client; + wait_info->type = MS_DRI2_WAIT_MSC; + + if (!ms_dri2_add_frame_event(wait_info)) { + free(wait_info); + wait_info = NULL; + goto out_complete; + } + + /* Get current count */ + ret = ms_get_crtc_ust_msc(crtc, ¤t_ust, ¤t_msc); + + /* + * If divisor is zero, or current_msc is smaller than target_msc, + * we just need to make sure target_msc passes before waking up the + * client. + */ + if (divisor == 0 || current_msc < target_msc) { + /* If target_msc already reached or passed, set it to + * current_msc to ensure we return a reasonable value back + * to the caller. This keeps the client from continually + * sending us MSC targets from the past by forcibly updating + * their count on this call. + */ + seq = ms_drm_queue_alloc(crtc, wait_info, + ms_dri2_frame_event_handler, + ms_dri2_frame_event_abort); + if (!seq) + goto out_free; + + if (current_msc >= target_msc) + target_msc = current_msc; + vbl.request.type = (DRM_VBLANK_ABSOLUTE | + DRM_VBLANK_EVENT | + drmmode_crtc->vblank_pipe); + vbl.request.sequence = ms_crtc_msc_to_kernel_msc(crtc, target_msc); + vbl.request.signal = (unsigned long)seq; + + ret = drmWaitVBlank(ms->fd, &vbl); + if (ret) { + static int limit = 5; + if (limit) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "%s:%d get vblank counter failed: %s\n", + __FUNCTION__, __LINE__, + strerror(errno)); + limit--; + } + goto out_free; + } + + wait_info->frame = ms_kernel_msc_to_crtc_msc(crtc, vbl.reply.sequence); + DRI2BlockClient(client, draw); + return TRUE; + } + + /* + * If we get here, target_msc has already passed or we don't have one, + * so we queue an event that will satisfy the divisor/remainder equation. + */ + vbl.request.type = + DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | drmmode_crtc->vblank_pipe; + + request_msc = current_msc - (current_msc % divisor) + + remainder; + /* + * If calculated remainder is larger than requested remainder, + * it means we've passed the last point where + * seq % divisor == remainder, so we need to wait for the next time + * that will happen. + */ + if ((current_msc % divisor) >= remainder) + request_msc += divisor; + + seq = ms_drm_queue_alloc(crtc, wait_info, + ms_dri2_frame_event_handler, + ms_dri2_frame_event_abort); + if (!seq) + goto out_free; + + vbl.request.sequence = ms_crtc_msc_to_kernel_msc(crtc, request_msc); + vbl.request.signal = (unsigned long)seq; + + ret = drmWaitVBlank(ms->fd, &vbl); + if (ret) { + static int limit = 5; + if (limit) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "%s:%d get vblank counter failed: %s\n", + __FUNCTION__, __LINE__, + strerror(errno)); + limit--; + } + goto out_free; + } + + wait_info->frame = ms_kernel_msc_to_crtc_msc(crtc, vbl.reply.sequence); + DRI2BlockClient(client, draw); + + return TRUE; + + out_free: + ms_dri2_del_frame_event(wait_info); + out_complete: + DRI2WaitMSCComplete(client, draw, target_msc, 0, 0); + return TRUE; +} + +/** + * ScheduleSwap is responsible for requesting a DRM vblank event for + * the appropriate frame, or executing the swap immediately if it + * doesn't need to wait. + * + * When the swap is complete, the driver should call into the server so it + * can send any swap complete events that have been requested. + */ +static int +ms_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, + DRI2BufferPtr front, DRI2BufferPtr back, + CARD64 *target_msc, CARD64 divisor, + CARD64 remainder, DRI2SwapEventPtr func, void *data) +{ + ScreenPtr screen = draw->pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); + drmVBlank vbl; + int ret; + xf86CrtcPtr crtc = ms_dri2_crtc_covering_drawable(draw); + drmmode_crtc_private_ptr drmmode_crtc; + ms_dri2_frame_event_ptr frame_info = NULL; + uint64_t current_msc, current_ust; + uint64_t request_msc; + uint32_t seq; + + /* Drawable not displayed... just complete the swap */ + if (!crtc) + goto blit_fallback; + drmmode_crtc = crtc->driver_private; + + frame_info = calloc(1, sizeof(*frame_info)); + if (!frame_info) + goto blit_fallback; + + frame_info->screen = screen; + frame_info->drawable = draw; + frame_info->client = client; + frame_info->event_complete = func; + frame_info->event_data = data; + frame_info->front = front; + frame_info->back = back; + frame_info->crtc = crtc; + frame_info->type = MS_DRI2_QUEUE_SWAP; + + if (!ms_dri2_add_frame_event(frame_info)) { + free(frame_info); + frame_info = NULL; + goto blit_fallback; + } + + ms_dri2_reference_buffer(front); + ms_dri2_reference_buffer(back); + + ret = ms_get_crtc_ust_msc(crtc, ¤t_ust, ¤t_msc); + + /* + * If divisor is zero, or current_msc is smaller than target_msc + * we just need to make sure target_msc passes before initiating + * the swap. + */ + if (divisor == 0 || current_msc < *target_msc) { + /* We need to use DRM_VBLANK_NEXTONMISS to avoid unreliable + * timestamping later on. + */ + vbl.request.type = (DRM_VBLANK_ABSOLUTE | + DRM_VBLANK_NEXTONMISS | + DRM_VBLANK_EVENT | + drmmode_crtc->vblank_pipe); + + /* If target_msc already reached or passed, set it to + * current_msc to ensure we return a reasonable value back + * to the caller. This makes swap_interval logic more robust. + */ + if (current_msc >= *target_msc) + *target_msc = current_msc; + + seq = ms_drm_queue_alloc(crtc, frame_info, + ms_dri2_frame_event_handler, + ms_dri2_frame_event_abort); + if (!seq) + goto blit_fallback; + + vbl.request.sequence = ms_crtc_msc_to_kernel_msc(crtc, *target_msc); + vbl.request.signal = (unsigned long)seq; + + ret = drmWaitVBlank(ms->fd, &vbl); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "divisor 0 get vblank counter failed: %s\n", + strerror(errno)); + goto blit_fallback; + } + + *target_msc = ms_kernel_msc_to_crtc_msc(crtc, vbl.reply.sequence); + frame_info->frame = *target_msc; + + return TRUE; + } + + /* + * If we get here, target_msc has already passed or we don't have one, + * and we need to queue an event that will satisfy the divisor/remainder + * equation. + */ + vbl.request.type = (DRM_VBLANK_ABSOLUTE | + DRM_VBLANK_NEXTONMISS | + DRM_VBLANK_EVENT | + drmmode_crtc->vblank_pipe); + + request_msc = current_msc - (current_msc % divisor) + + remainder; + + /* + * If the calculated deadline vbl.request.sequence is smaller than + * or equal to current_msc, it means we've passed the last point + * when effective onset frame seq could satisfy + * seq % divisor == remainder, so we need to wait for the next time + * this will happen. + + * This comparison takes the DRM_VBLANK_NEXTONMISS delay into account. + */ + if (request_msc <= current_msc) + request_msc += divisor; + + + seq = ms_drm_queue_alloc(crtc, frame_info, + ms_dri2_frame_event_handler, + ms_dri2_frame_event_abort); + if (!seq) + goto blit_fallback; + + vbl.request.sequence = ms_crtc_msc_to_kernel_msc(crtc, request_msc); + vbl.request.signal = (unsigned long)seq; + + ret = drmWaitVBlank(ms->fd, &vbl); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "final get vblank counter failed: %s\n", + strerror(errno)); + goto blit_fallback; + } + + *target_msc = ms_kernel_msc_to_crtc_msc(crtc, vbl.reply.sequence); + frame_info->frame = *target_msc; + + return TRUE; + + blit_fallback: + ms_dri2_blit_swap(draw, front, back); + DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data); + if (frame_info) + ms_dri2_del_frame_event(frame_info); + *target_msc = 0; /* offscreen, so zero out target vblank count */ + return TRUE; +} + +static int +ms_dri2_frame_event_client_gone(void *data, XID id) +{ + struct ms_dri2_resource *resource = data; + + while (!xorg_list_is_empty(&resource->list)) { + ms_dri2_frame_event_ptr info = + xorg_list_first_entry(&resource->list, + ms_dri2_frame_event_rec, + client_resource); + + xorg_list_del(&info->client_resource); + info->client = NULL; + } + free(resource); + + return Success; +} + +static int +ms_dri2_frame_event_drawable_gone(void *data, XID id) +{ + struct ms_dri2_resource *resource = data; + + while (!xorg_list_is_empty(&resource->list)) { + ms_dri2_frame_event_ptr info = + xorg_list_first_entry(&resource->list, + ms_dri2_frame_event_rec, + drawable_resource); + + xorg_list_del(&info->drawable_resource); + info->drawable = NULL; + } + free(resource); + + return Success; +} + +static Bool +ms_dri2_register_frame_event_resource_types(void) +{ + frame_event_client_type = + CreateNewResourceType(ms_dri2_frame_event_client_gone, + "Frame Event Client"); + if (!frame_event_client_type) + return FALSE; + + frame_event_drawable_type = + CreateNewResourceType(ms_dri2_frame_event_drawable_gone, + "Frame Event Drawable"); + if (!frame_event_drawable_type) + return FALSE; + + return TRUE; +} + +Bool +ms_dri2_screen_init(ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); + DRI2InfoRec info; + + if (!glamor_supports_pixmap_import_export(screen)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "DRI2: glamor lacks support for pixmap import/export\n"); + } + + if (!xf86LoaderCheckSymbol("DRI2Version")) + return FALSE; + + if (!dixRegisterPrivateKey(&ms_dri2_client_key, + PRIVATE_CLIENT, sizeof(XID))) + return FALSE; + + if (serverGeneration != ms_dri2_server_generation) { + ms_dri2_server_generation = serverGeneration; + if (!ms_dri2_register_frame_event_resource_types()) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Cannot register DRI2 frame event resources\n"); + return FALSE; + } + } + + memset(&info, '\0', sizeof(info)); + info.fd = ms->fd; + info.driverName = NULL; /* Compat field, unused. */ + info.deviceName = drmGetDeviceNameFromFd(ms->fd); + + info.version = 4; + info.CreateBuffer = ms_dri2_create_buffer; + info.DestroyBuffer = ms_dri2_destroy_buffer; + info.CopyRegion = ms_dri2_copy_region; + info.ScheduleSwap = ms_dri2_schedule_swap; + info.GetMSC = ms_dri2_get_msc; + info.ScheduleWaitMSC = ms_dri2_schedule_wait_msc; + + /* These two will be filled in by dri2.c */ + info.numDrivers = 0; + info.driverNames = NULL; + + return DRI2ScreenInit(screen, &info); +} + +void +ms_dri2_close_screen(ScreenPtr screen) +{ + DRI2CloseScreen(screen); +} + +#endif /* GLAMOR */ diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c index c62147a0f..e0391dbc3 100644 --- a/hw/xfree86/drivers/modesetting/driver.c +++ b/hw/xfree86/drivers/modesetting/driver.c @@ -788,7 +788,9 @@ PreInit(ScrnInfoPtr pScrn, int flags) try_enable_glamor(pScrn); - if (!ms->glamor) { + if (ms->glamor) { + xf86LoadSubModule(pScrn, "dri2"); + } else { Bool prefer_shadow = TRUE; ret = drmGetCap(ms->fd, DRM_CAP_DUMB_PREFER_SHADOW, &value); @@ -1107,6 +1109,21 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv) if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); + if (!ms_vblank_screen_init(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to initialize vblank support.\n"); + return FALSE; + } + +#ifdef GLAMOR + if (ms->glamor) { + if (!ms_dri2_screen_init(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to initialize the DRI2 extension.\n"); + } + } +#endif + return EnterVT(pScrn); } @@ -1172,6 +1189,14 @@ CloseScreen(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); modesettingPtr ms = modesettingPTR(pScrn); +#ifdef GLAMOR + if (ms->glamor) { + ms_dri2_close_screen(pScreen); + } +#endif + + ms_vblank_close_screen(pScreen); + if (ms->damage) { DamageUnregister(ms->damage); DamageDestroy(ms->damage); diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h index 35f24193a..9eda1c4da 100644 --- a/hw/xfree86/drivers/modesetting/driver.h +++ b/hw/xfree86/drivers/modesetting/driver.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "drmmode_display.h" @@ -42,6 +43,26 @@ typedef struct { ScrnInfoPtr pScrn_2; } EntRec, *EntPtr; +typedef void (*ms_drm_handler_proc)(uint64_t frame, + uint64_t usec, + void *data); + +typedef void (*ms_drm_abort_proc)(void *data); + +/** + * A tracked handler for an event that will hopefully be generated by + * the kernel, and what to do when it is encountered. + */ +struct ms_drm_queue { + struct xorg_list list; + xf86CrtcPtr crtc; + uint32_t seq; + void *data; + ScrnInfoPtr scrn; + ms_drm_handler_proc handler; + ms_drm_abort_proc abort; +}; + typedef struct _modesettingRec { int fd; @@ -70,6 +91,8 @@ typedef struct _modesettingRec { drmmode_rec drmmode; + drmEventContext event_context; + DamagePtr damage; Bool dirty_enabled; @@ -78,3 +101,24 @@ typedef struct _modesettingRec { } modesettingRec, *modesettingPtr; #define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate)) + +uint32_t ms_drm_queue_alloc(xf86CrtcPtr crtc, + void *data, + ms_drm_handler_proc handler, + ms_drm_abort_proc abort); + +xf86CrtcPtr ms_dri2_crtc_covering_drawable(DrawablePtr pDraw); +xf86CrtcPtr ms_covering_crtc(ScrnInfoPtr scrn, BoxPtr box, + xf86CrtcPtr desired, BoxPtr crtc_box_ret); + +int ms_get_crtc_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc); + +uint32_t ms_crtc_msc_to_kernel_msc(xf86CrtcPtr crtc, uint64_t expect); +uint64_t ms_kernel_msc_to_crtc_msc(xf86CrtcPtr crtc, uint32_t sequence); + + +Bool ms_dri2_screen_init(ScreenPtr screen); +void ms_dri2_close_screen(ScreenPtr screen); + +Bool ms_vblank_screen_init(ScreenPtr screen); +void ms_vblank_close_screen(ScreenPtr screen); diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c index d959837ae..ef9009e98 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.c +++ b/hw/xfree86/drivers/modesetting/drmmode_display.c @@ -116,7 +116,7 @@ dumb_bo_unmap(int fd, struct dumb_bo *bo) } #endif -static int +int dumb_bo_destroy(int fd, struct dumb_bo *bo) { struct drm_mode_destroy_dumb arg; @@ -137,8 +137,8 @@ dumb_bo_destroy(int fd, struct dumb_bo *bo) return 0; } -static struct dumb_bo * -dumb_get_bo_from_handle(int fd, int handle, int pitch, int size) +struct dumb_bo * +dumb_get_bo_from_fd(int fd, int handle, int pitch, int size) { struct dumb_bo *bo; int ret; @@ -164,7 +164,7 @@ drmmode_SetSlaveBO(PixmapPtr ppix, msPixmapPrivPtr ppriv = msGetPixmapPriv(drmmode, ppix); ppriv->backing_bo = - dumb_get_bo_from_handle(drmmode->fd, fd_handle, pitch, size); + dumb_get_bo_from_fd(drmmode->fd, fd_handle, pitch, size); if (!ppriv->backing_bo) return FALSE; @@ -582,6 +582,17 @@ static const xf86CrtcFuncsRec drmmode_crtc_funcs = { .shadow_create = drmmode_shadow_create, }; +static uint32_t +drmmode_crtc_vblank_pipe(int crtc_id) +{ + if (crtc_id > 1) + return crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT; + else if (crtc_id > 0) + return DRM_VBLANK_SECONDARY; + else + return 0; +} + static void drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) { @@ -596,6 +607,7 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]); drmmode_crtc->drmmode = drmmode; + drmmode_crtc->vblank_pipe = drmmode_crtc_vblank_pipe(num); crtc->driver_private = drmmode_crtc; } @@ -1183,6 +1195,11 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) xf86DrvMsg(scrn->scrnIndex, X_INFO, "Allocate new frame buffer %dx%d stride\n", width, height); + if (drmmode->triple_buffer_pixmap) { + screen->DestroyPixmap(drmmode->triple_buffer_pixmap); + drmmode->triple_buffer_pixmap = NULL; + } + old_width = scrn->virtualX; old_height = scrn->virtualY; old_pitch = drmmode->front_bo->pitch; diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h index 438743b01..987608c55 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.h +++ b/hw/xfree86/drivers/modesetting/drmmode_display.h @@ -43,6 +43,7 @@ struct dumb_bo { typedef struct { int fd; unsigned fb_id; + unsigned old_fb_id; drmModeResPtr mode_res; drmModeFBPtr mode_fb; int cpp; @@ -58,17 +59,42 @@ typedef struct { Bool shadow_enable; void *shadow_fb; + /** + * A screen-sized pixmap when we're doing triple-buffered DRI2 + * pageflipping. + * + * One is shared between all drawables that flip to the front + * buffer, and it only gets reallocated when root pixmap size + * changes. + */ + PixmapPtr triple_buffer_pixmap; + + /** The GEM name for triple_buffer_pixmap */ + uint32_t triple_buffer_name; + DevPrivateKeyRec pixmapPrivateKeyRec; } drmmode_rec, *drmmode_ptr; typedef struct { drmmode_ptr drmmode; drmModeCrtcPtr mode_crtc; - int hw_id; + uint32_t vblank_pipe; struct dumb_bo *cursor_bo; unsigned rotate_fb_id; uint16_t lut_r[256], lut_g[256], lut_b[256]; DamagePtr slave_damage; + + /** + * @{ MSC (vblank count) handling for the PRESENT extension. + * + * The kernel's vblank counters are 32 bits and apparently full of + * lies, and we need to give a reliable 64-bit msc for GL, so we + * have to track and convert to a userland-tracked 64-bit msc. + */ + int32_t vblank_offset; + uint32_t msc_prev; + uint64_t msc_high; + /** @} */ } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr; typedef struct { @@ -121,6 +147,9 @@ Bool drmmode_map_cursor_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode); void drmmode_free_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode); void drmmode_get_default_bpp(ScrnInfoPtr pScrn, drmmode_ptr drmmmode, int *depth, int *bpp); +struct dumb_bo *dumb_get_bo_from_fd(int drm_fd, int fd, int pitch, int size); +int dumb_bo_destroy(int fd, struct dumb_bo *bo); + #ifndef DRM_CAP_DUMB_PREFERRED_DEPTH #define DRM_CAP_DUMB_PREFERRED_DEPTH 3 diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c new file mode 100644 index 000000000..35cadb222 --- /dev/null +++ b/hw/xfree86/drivers/modesetting/vblank.c @@ -0,0 +1,382 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/** @file vblank.c + * + * Support for tracking the DRM's vblank events. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include "dix-config.h" +#endif + +#include +#include +#include +#include +#include "driver.h" +#include "drmmode_display.h" + +/** + * Tracking for outstanding events queued to the kernel. + * + * Each list entry is a struct ms_drm_queue, which has a uint32_t + * value generated from drm_seq that identifies the event and a + * reference back to the crtc/screen associated with the event. It's + * done this way rather than in the screen because we want to be able + * to drain the list of event handlers that should be called at server + * regen time, even though we don't close the drm fd and have no way + * to actually drain the kernel events. + */ +static struct xorg_list ms_drm_queue; +static uint32_t ms_drm_seq; + +struct ms_pageflip { + ScreenPtr screen; + Bool crtc_for_msc_ust; +}; + +static void ms_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) +{ + dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; + dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; + if (dest->x1 >= dest->x2) { + dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; + return; + } + + dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; + dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; + if (dest->y1 >= dest->y2) + dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; +} + +static void ms_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) +{ + if (crtc->enabled) { + crtc_box->x1 = crtc->x; + crtc_box->x2 = + crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); + crtc_box->y1 = crtc->y; + crtc_box->y2 = + crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); + } else + crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; +} + +static int ms_box_area(BoxPtr box) +{ + return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1); +} + +/* + * Return the crtc covering 'box'. If two crtcs cover a portion of + * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc + * with greater coverage + */ + +xf86CrtcPtr +ms_covering_crtc(ScrnInfoPtr scrn, + BoxPtr box, xf86CrtcPtr desired, BoxPtr crtc_box_ret) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + xf86CrtcPtr crtc, best_crtc; + int coverage, best_coverage; + int c; + BoxRec crtc_box, cover_box; + + best_crtc = NULL; + best_coverage = 0; + crtc_box_ret->x1 = 0; + crtc_box_ret->x2 = 0; + crtc_box_ret->y1 = 0; + crtc_box_ret->y2 = 0; + for (c = 0; c < xf86_config->num_crtc; c++) { + crtc = xf86_config->crtc[c]; + + /* If the CRTC is off, treat it as not covering */ + if (!crtc->enabled) + continue; + + ms_crtc_box(crtc, &crtc_box); + ms_box_intersect(&cover_box, &crtc_box, box); + coverage = ms_box_area(&cover_box); + if (coverage && crtc == desired) { + *crtc_box_ret = crtc_box; + return crtc; + } + if (coverage > best_coverage) { + *crtc_box_ret = crtc_box; + best_crtc = crtc; + best_coverage = coverage; + } + } + return best_crtc; +} + +xf86CrtcPtr +ms_dri2_crtc_covering_drawable(DrawablePtr pDraw) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + BoxRec box, crtcbox; + xf86CrtcPtr crtc; + + box.x1 = pDraw->x; + box.y1 = pDraw->y; + box.x2 = box.x1 + pDraw->width; + box.y2 = box.y1 + pDraw->height; + + crtc = ms_covering_crtc(pScrn, &box, NULL, &crtcbox); + + /* Make sure the CRTC is valid and this is the real front buffer */ + if (crtc != NULL && !crtc->rotatedData) + return crtc; + + return NULL; +} + +static Bool +ms_get_kernel_ust_msc(xf86CrtcPtr crtc, + uint32_t *msc, uint64_t *ust) +{ + ScreenPtr screen = crtc->randr_crtc->pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmVBlank vbl; + int ret; + + /* Get current count */ + vbl.request.type = DRM_VBLANK_RELATIVE | drmmode_crtc->vblank_pipe; + vbl.request.sequence = 0; + vbl.request.signal = 0; + ret = drmWaitVBlank(ms->fd, &vbl); + if (ret) { + *msc = 0; + *ust = 0; + return FALSE; + } else { + *msc = vbl.reply.sequence; + *ust = (CARD64) vbl.reply.tval_sec * 1000000 + vbl.reply.tval_usec; + return TRUE; + } +} + +/** + * Convert a 32-bit kernel MSC sequence number to a 64-bit local sequence + * number, adding in the vblank_offset and high 32 bits, and dealing + * with 64-bit wrapping + */ +uint64_t +ms_kernel_msc_to_crtc_msc(xf86CrtcPtr crtc, uint32_t sequence) +{ + drmmode_crtc_private_rec *drmmode_crtc = crtc->driver_private; + sequence += drmmode_crtc->vblank_offset; + + if ((int32_t) (sequence - drmmode_crtc->msc_prev) < -0x40000000) + drmmode_crtc->msc_high += 0x100000000L; + drmmode_crtc->msc_prev = sequence; + return drmmode_crtc->msc_high + sequence; +} + +int +ms_get_crtc_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc) +{ + uint32_t kernel_msc; + + if (!ms_get_kernel_ust_msc(crtc, &kernel_msc, ust)) + return BadMatch; + *msc = ms_kernel_msc_to_crtc_msc(crtc, kernel_msc); + + return Success; +} + +#define MAX_VBLANK_OFFSET 1000 + +/** + * Convert a 64-bit adjusted MSC value into a 32-bit kernel sequence number, + * removing the high 32 bits and subtracting out the vblank_offset term. + * + * This also updates the vblank_offset when it notices that the value should + * change. + */ +uint32_t +ms_crtc_msc_to_kernel_msc(xf86CrtcPtr crtc, uint64_t expect) +{ + drmmode_crtc_private_rec *drmmode_crtc = crtc->driver_private; + uint64_t msc; + uint64_t ust; + int64_t diff; + + ms_get_crtc_ust_msc(crtc, &ust, &msc); + diff = expect - msc; + + /* We're way off here, assume that the kernel has lost its mind + * and smack the vblank back to something sensible + */ + if (diff < -MAX_VBLANK_OFFSET || MAX_VBLANK_OFFSET < diff) { + drmmode_crtc->vblank_offset += (int32_t) diff; + if (drmmode_crtc->vblank_offset > -MAX_VBLANK_OFFSET && + drmmode_crtc->vblank_offset < MAX_VBLANK_OFFSET) + drmmode_crtc->vblank_offset = 0; + } + return (uint32_t) (expect - drmmode_crtc->vblank_offset); +} + +/** + * Check for pending DRM events and process them. + */ +static void +ms_drm_wakeup_handler(void *data, int err, void *mask) +{ + ScreenPtr screen = data; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); + fd_set *read_mask = mask; + + if (data == NULL || err < 0) + return; + + if (FD_ISSET(ms->fd, read_mask)) + drmHandleEvent(ms->fd, &ms->event_context); +} + +/* + * Enqueue a potential drm response; when the associated response + * appears, we've got data to pass to the handler from here + */ +uint32_t +ms_drm_queue_alloc(xf86CrtcPtr crtc, + void *data, + ms_drm_handler_proc handler, + ms_drm_abort_proc abort) +{ + ScreenPtr screen = crtc->randr_crtc->pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + struct ms_drm_queue *q; + + q = calloc(1, sizeof(struct ms_drm_queue)); + + if (!q) + return 0; + if (!ms_drm_seq) + ++ms_drm_seq; + q->seq = ms_drm_seq++; + q->scrn = scrn; + q->crtc = crtc; + q->data = data; + q->handler = handler; + q->abort = abort; + + xorg_list_add(&q->list, &ms_drm_queue); + + return q->seq; +} + +/** + * Abort one queued DRM entry, removing it + * from the list, calling the abort function and + * freeing the memory + */ +static void +ms_drm_abort_one(struct ms_drm_queue *q) +{ + xorg_list_del(&q->list); + q->abort(q->data); + free(q); +} + +/** + * Abort all queued entries on a specific scrn, used + * when resetting the X server + */ +static void +ms_drm_abort_scrn(ScrnInfoPtr scrn) +{ + struct ms_drm_queue *q, *tmp; + + xorg_list_for_each_entry_safe(q, tmp, &ms_drm_queue, list) { + if (q->scrn == scrn) + ms_drm_abort_one(q); + } +} + +/* + * General DRM kernel handler. Looks for the matching sequence number in the + * drm event queue and calls the handler for it. + */ +static void +ms_drm_handler(int fd, uint32_t frame, uint32_t sec, uint32_t usec, + void *user_ptr) +{ + struct ms_drm_queue *q, *tmp; + uint32_t user_data = (uint32_t) (intptr_t) user_ptr; + + xorg_list_for_each_entry_safe(q, tmp, &ms_drm_queue, list) { + if (q->seq == user_data) { + uint64_t msc; + + msc = ms_kernel_msc_to_crtc_msc(q->crtc, frame); + xorg_list_del(&q->list); + q->handler(msc, (uint64_t) sec * 1000000 + usec, q->data); + free(q); + break; + } + } +} + +Bool +ms_vblank_screen_init(ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); + + xorg_list_init(&ms_drm_queue); + + ms->event_context.version = DRM_EVENT_CONTEXT_VERSION; + ms->event_context.vblank_handler = ms_drm_handler; + ms->event_context.page_flip_handler = ms_drm_handler; + + /* We need to re-register the DRM fd for the synchronisation + * feedback on every server generation, so perform the + * registration within ScreenInit and not PreInit. + */ + AddGeneralSocket(ms->fd); + RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, + ms_drm_wakeup_handler, screen); + + return TRUE; +} + +void +ms_vblank_close_screen(ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); + + ms_drm_abort_scrn(scrn); + + RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, + ms_drm_wakeup_handler, screen); + RemoveGeneralSocket(ms->fd); +}