Module Name: xsrc
Committed By: snj
Date: Fri Jan 16 21:32:11 UTC 2015
Modified Files:
xsrc/external/mit/xf86-video-intel/dist/src: backlight.c
xsrc/external/mit/xf86-video-intel/dist/src/sna: kgem.c sna_display.c
xsrc/external/mit/xf86-video-intel/dist/src/uxa: intel.h
Removed Files:
xsrc/external/mit/xf86-video-intel/dist/src/uxa: intel_glamor.c
intel_glamor.h uxa-glamor.h
Log Message:
merge conflicts
To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 \
xsrc/external/mit/xf86-video-intel/dist/src/backlight.c
cvs rdiff -u -r1.3 -r1.4 \
xsrc/external/mit/xf86-video-intel/dist/src/sna/kgem.c
cvs rdiff -u -r1.2 -r1.3 \
xsrc/external/mit/xf86-video-intel/dist/src/sna/sna_display.c
cvs rdiff -u -r1.2 -r1.3 \
xsrc/external/mit/xf86-video-intel/dist/src/uxa/intel.h
cvs rdiff -u -r1.1.1.2 -r0 \
xsrc/external/mit/xf86-video-intel/dist/src/uxa/intel_glamor.c \
xsrc/external/mit/xf86-video-intel/dist/src/uxa/intel_glamor.h
cvs rdiff -u -r1.1.1.1 -r0 \
xsrc/external/mit/xf86-video-intel/dist/src/uxa/uxa-glamor.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/xf86-video-intel/dist/src/backlight.c
diff -u xsrc/external/mit/xf86-video-intel/dist/src/backlight.c:1.2 xsrc/external/mit/xf86-video-intel/dist/src/backlight.c:1.3
--- xsrc/external/mit/xf86-video-intel/dist/src/backlight.c:1.2 Wed Nov 5 17:58:59 2014
+++ xsrc/external/mit/xf86-video-intel/dist/src/backlight.c Fri Jan 16 21:32:11 2015
@@ -81,6 +81,7 @@ void backlight_init(struct backlight *b)
b->fd = -1;
b->pid = -1;
b->max = -1;
+ b->has_power = 0;
}
#if defined(__OpenBSD__) || defined(__NetBSD__)
@@ -153,6 +154,15 @@ enum backlight_type backlight_exists(con
return BL_PLATFORM;
}
+int backlight_on(struct backlight *b)
+{
+ return 0;
+}
+
+int backlight_off(struct backlight *b)
+{
+ return 0;
+}
#else
static int
@@ -202,6 +212,21 @@ __backlight_read(const char *iface, cons
return val;
}
+static int
+__backlight_write(const char *iface, const char *file, const char *value)
+{
+ int fd, ret;
+
+ fd = __backlight_open(iface, file, O_WRONLY);
+ if (fd < 0)
+ return -1;
+
+ ret = write(fd, value, strlen(value)+1);
+ close(fd);
+
+ return ret;
+}
+
/* List of available kernel interfaces in priority order */
static const char *known_interfaces[] = {
"dell_backlight",
@@ -284,6 +309,9 @@ static int __backlight_direct_init(struc
if (fd < 0)
return 0;
+ if (__backlight_read(iface, "bl_power") != -1)
+ b->has_power = 1;
+
return __backlight_init(b, iface, fd);
}
@@ -448,6 +476,30 @@ int backlight_get(struct backlight *b)
level = -1;
return level;
}
+
+int backlight_off(struct backlight *b)
+{
+ if (b->iface == NULL)
+ return 0;
+
+ if (!b->has_power)
+ return 0;
+
+ /* 4 -> FB_BLANK_POWERDOWN */
+ return __backlight_write(b->iface, "bl_power", "4");
+}
+
+int backlight_on(struct backlight *b)
+{
+ if (b->iface == NULL)
+ return 0;
+
+ if (!b->has_power)
+ return 0;
+
+ /* 0 -> FB_BLANK_UNBLANK */
+ return __backlight_write(b->iface, "bl_power", "0");
+}
#endif
void backlight_disable(struct backlight *b)
Index: xsrc/external/mit/xf86-video-intel/dist/src/sna/kgem.c
diff -u xsrc/external/mit/xf86-video-intel/dist/src/sna/kgem.c:1.3 xsrc/external/mit/xf86-video-intel/dist/src/sna/kgem.c:1.4
--- xsrc/external/mit/xf86-video-intel/dist/src/sna/kgem.c:1.3 Wed Nov 5 17:58:59 2014
+++ xsrc/external/mit/xf86-video-intel/dist/src/sna/kgem.c Fri Jan 16 21:32:11 2015
@@ -79,9 +79,11 @@ search_snoop_cache(struct kgem *kgem, un
#define DBG_NO_RELAXED_FENCING 0
#define DBG_NO_SECURE_BATCHES 0
#define DBG_NO_PINNED_BATCHES 0
+#define DBG_NO_SHRINK_BATCHES 0
#define DBG_NO_FAST_RELOC 0
#define DBG_NO_HANDLE_LUT 0
#define DBG_NO_WT 0
+#define DBG_NO_WC_MMAP 0
#define DBG_DUMP 0
#define DBG_NO_MALLOC_CACHE 0
@@ -94,6 +96,11 @@ search_snoop_cache(struct kgem *kgem, un
#define SHOW_BATCH_BEFORE 0
#define SHOW_BATCH_AFTER 0
+#if !USE_WC_MMAP
+#undef DBG_NO_WC_MMAP
+#define DBG_NO_WC_MMAP 1
+#endif
+
#if 0
#define ASSERT_IDLE(kgem__, handle__) assert(!__kgem_busy(kgem__, handle__))
#define ASSERT_MAYBE_IDLE(kgem__, handle__, expect__) assert(!(expect__) || !__kgem_busy(kgem__, handle__))
@@ -126,12 +133,14 @@ search_snoop_cache(struct kgem *kgem, un
#define LOCAL_I915_PARAM_HAS_BLT 11
#define LOCAL_I915_PARAM_HAS_RELAXED_FENCING 12
#define LOCAL_I915_PARAM_HAS_RELAXED_DELTA 15
+#define LOCAL_I915_PARAM_HAS_LLC 17
#define LOCAL_I915_PARAM_HAS_SEMAPHORES 20
#define LOCAL_I915_PARAM_HAS_SECURE_BATCHES 23
#define LOCAL_I915_PARAM_HAS_PINNED_BATCHES 24
#define LOCAL_I915_PARAM_HAS_NO_RELOC 25
#define LOCAL_I915_PARAM_HAS_HANDLE_LUT 26
#define LOCAL_I915_PARAM_HAS_WT 27
+#define LOCAL_I915_PARAM_MMAP_VERSION 30
#define LOCAL_I915_EXEC_IS_PINNED (1<<10)
#define LOCAL_I915_EXEC_NO_RELOC (1<<11)
@@ -178,6 +187,17 @@ struct local_i915_gem_caching {
#define LOCAL_IOCTL_I915_GEM_SET_CACHING DRM_IOW(DRM_COMMAND_BASE + LOCAL_I915_GEM_SET_CACHING, struct local_i915_gem_caching)
#define LOCAL_IOCTL_I915_GEM_GET_CACHING DRM_IOW(DRM_COMMAND_BASE + LOCAL_I915_GEM_GET_CACHING, struct local_i915_gem_caching)
+struct local_i915_gem_mmap2 {
+ uint32_t handle;
+ uint32_t pad;
+ uint64_t offset;
+ uint64_t size;
+ uint64_t addr_ptr;
+ uint64_t flags;
+#define I915_MMAP_WC 0x1
+};
+#define LOCAL_IOCTL_I915_GEM_MMAP_v2 DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct local_i915_gem_mmap2)
+
struct kgem_buffer {
struct kgem_bo base;
void *mem;
@@ -282,6 +302,13 @@ static void assert_bo_retired(struct kge
#define assert_bo_retired(bo)
#endif
+static void
+__kgem_set_wedged(struct kgem *kgem)
+{
+ kgem->wedged = true;
+ sna_render_mark_wedged(container_of(kgem, struct sna, kgem));
+}
+
static void kgem_sna_reset(struct kgem *kgem)
{
struct sna *sna = container_of(kgem, struct sna, kgem);
@@ -403,24 +430,21 @@ static bool __kgem_throttle_retire(struc
static void *__kgem_bo_map__gtt(struct kgem *kgem, struct kgem_bo *bo)
{
- struct drm_i915_gem_mmap_gtt mmap_arg;
+ struct drm_i915_gem_mmap_gtt gtt;
void *ptr;
int err;
DBG(("%s(handle=%d, size=%d)\n", __FUNCTION__,
bo->handle, bytes(bo)));
- assert(bo->proxy == NULL);
- assert(!bo->snoop);
- assert(num_pages(bo) <= kgem->aperture_mappable / 4);
+ VG_CLEAR(gtt);
retry_gtt:
- VG_CLEAR(mmap_arg);
- mmap_arg.handle = bo->handle;
+ gtt.handle = bo->handle;
#ifdef __NetBSD__
- if (drmIoctl(kgem->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg)) {
+ if (drmIoctl(kgem->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, >t)) {
err = errno;
#else
- if ((err = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg))) {
+ if ((err = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, >t))) {
#endif
assert(err != EINVAL);
@@ -438,11 +462,11 @@ retry_gtt:
retry_mmap:
#ifdef __NetBSD__
- err = -drmMap(kgem->fd, mmap_arg.offset, bytes(bo), &ptr);
+ err = -drmMap(kgem->fd, gtt.offset, bytes(bo), &ptr);
if (err) {
#else
ptr = mmap(0, bytes(bo), PROT_READ | PROT_WRITE, MAP_SHARED,
- kgem->fd, mmap_arg.offset);
+ kgem->fd, gtt.offset);
if (ptr == MAP_FAILED) {
err = errno;
#endif
@@ -459,7 +483,78 @@ retry_mmap:
ptr = NULL;
}
- return ptr;
+ /* Cache this mapping to avoid the overhead of an
+ * excruciatingly slow GTT pagefault. This is more an
+ * issue with compositing managers which need to
+ * frequently flush CPU damage to their GPU bo.
+ */
+ return bo->map__gtt = ptr;
+}
+
+static void *__kgem_bo_map__wc(struct kgem *kgem, struct kgem_bo *bo)
+{
+ struct local_i915_gem_mmap2 wc;
+ int err;
+
+ DBG(("%s(handle=%d, size=%d)\n", __FUNCTION__,
+ bo->handle, bytes(bo)));
+ assert(kgem->has_wc_mmap);
+
+ VG_CLEAR(wc);
+
+retry_wc:
+ wc.handle = bo->handle;
+ wc.offset = 0;
+ wc.size = bytes(bo);
+ wc.flags = I915_MMAP_WC;
+ if ((err = do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_MMAP_v2, &wc))) {
+ assert(err != EINVAL);
+
+ if (__kgem_throttle_retire(kgem, 0))
+ goto retry_wc;
+
+ if (kgem_cleanup_cache(kgem))
+ goto retry_wc;
+
+ ERR(("%s: failed to mmap handle=%d, %d bytes, into CPU(wc) domain: %d\n",
+ __FUNCTION__, bo->handle, bytes(bo), -err));
+ return NULL;
+ }
+
+ VG(VALGRIND_MAKE_MEM_DEFINED(wc.addr_ptr, bytes(bo)));
+
+ DBG(("%s: caching CPU(wc) vma for %d\n", __FUNCTION__, bo->handle));
+ return bo->map__wc = (void *)(uintptr_t)wc.addr_ptr;
+}
+
+static void *__kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo)
+{
+ struct drm_i915_gem_mmap mmap_arg;
+ int err;
+
+retry:
+ VG_CLEAR(mmap_arg);
+ mmap_arg.handle = bo->handle;
+ mmap_arg.offset = 0;
+ mmap_arg.size = bytes(bo);
+ if ((err = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg))) {
+ assert(err != EINVAL);
+
+ if (__kgem_throttle_retire(kgem, 0))
+ goto retry;
+
+ if (kgem_cleanup_cache(kgem))
+ goto retry;
+
+ ERR(("%s: failed to mmap handle=%d, %d bytes, into CPU domain: %d\n",
+ __FUNCTION__, bo->handle, bytes(bo), -err));
+ return NULL;
+ }
+
+ VG(VALGRIND_MAKE_MEM_DEFINED(mmap_arg.addr_ptr, bytes(bo)));
+
+ DBG(("%s: caching CPU vma for %d\n", __FUNCTION__, bo->handle));
+ return bo->map__cpu = (void *)(uintptr_t)mmap_arg.addr_ptr;
}
static int gem_write(int fd, uint32_t handle,
@@ -583,6 +678,7 @@ static void kgem_bo_maybe_retire(struct
bool kgem_bo_write(struct kgem *kgem, struct kgem_bo *bo,
const void *data, int length)
{
+ void *ptr;
int err;
assert(bo->refcnt);
@@ -591,6 +687,22 @@ bool kgem_bo_write(struct kgem *kgem, st
assert(length <= bytes(bo));
retry:
+ ptr = NULL;
+ if (bo->domain == DOMAIN_CPU || (kgem->has_llc && !bo->scanout)) {
+ ptr = bo->map__cpu;
+ if (ptr == NULL)
+ ptr = __kgem_bo_map__cpu(kgem, bo);
+ } else if (kgem->has_wc_mmap) {
+ ptr = bo->map__wc;
+ if (ptr == NULL)
+ ptr = __kgem_bo_map__wc(kgem, bo);
+ }
+ if (ptr) {
+ /* XXX unsynchronized? */
+ memcpy(ptr, data, length);
+ return true;
+ }
+
if ((err = gem_write(kgem->fd, bo->handle, 0, length, data))) {
assert(err != EINVAL);
@@ -1031,9 +1143,7 @@ static bool test_has_llc(struct kgem *kg
if (DBG_NO_LLC)
return false;
-#if defined(I915_PARAM_HAS_LLC) /* Expected in libdrm-2.4.31 */
- has_llc = gem_param(kgem, I915_PARAM_HAS_LLC);
-#endif
+ has_llc = gem_param(kgem, LOCAL_I915_PARAM_HAS_LLC);
if (has_llc == -1) {
DBG(("%s: no kernel/drm support for HAS_LLC, assuming support for LLC based on GPU generation\n", __FUNCTION__));
has_llc = kgem->gen >= 060;
@@ -1042,6 +1152,28 @@ static bool test_has_llc(struct kgem *kg
return has_llc;
}
+static bool test_has_wc_mmap(struct kgem *kgem)
+{
+ struct local_i915_gem_mmap2 wc;
+ bool ret;
+
+ if (DBG_NO_WC_MMAP)
+ return false;
+
+ if (gem_param(kgem, LOCAL_I915_PARAM_MMAP_VERSION) < 1)
+ return false;
+
+ VG_CLEAR(wc);
+ wc.handle = gem_create(kgem->fd, 1);
+ wc.offset = 0;
+ wc.size = 4096;
+ wc.flags = I915_MMAP_WC;
+ ret = do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_MMAP_v2, &wc) == 0;
+ gem_close(kgem->fd, wc.handle);
+
+ return ret;
+}
+
static bool test_has_caching(struct kgem *kgem)
{
uint32_t handle;
@@ -1075,9 +1207,6 @@ static bool test_has_userptr(struct kgem
if (kgem->gen == 040)
return false;
- if (kgem->gen >= 0100)
- return false; /* FIXME https://bugs.freedesktop.org/show_bug.cgi?id=79053 */
-
if (posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE))
return false;
@@ -1237,10 +1366,13 @@ err:
static void kgem_init_swizzling(struct kgem *kgem)
{
- struct drm_i915_gem_get_tiling tiling;
-
- if (kgem->gen < 050) /* bit17 swizzling :( */
- return;
+ struct local_i915_gem_get_tiling_v2 {
+ uint32_t handle;
+ uint32_t tiling_mode;
+ uint32_t swizzle_mode;
+ uint32_t phys_swizzle_mode;
+ } tiling;
+#define LOCAL_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct local_i915_gem_get_tiling_v2)
VG_CLEAR(tiling);
tiling.handle = gem_create(kgem->fd, 1);
@@ -1250,7 +1382,10 @@ static void kgem_init_swizzling(struct k
if (!gem_set_tiling(kgem->fd, tiling.handle, I915_TILING_X, 512))
goto out;
- if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_GET_TILING, &tiling))
+ if (do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_GET_TILING, &tiling))
+ goto out;
+
+ if (kgem->gen < 50 && tiling.phys_swizzle_mode != tiling.swizzle_mode)
goto out;
choose_memcpy_tiled_x(kgem, tiling.swizzle_mode);
@@ -1258,6 +1393,117 @@ out:
gem_close(kgem->fd, tiling.handle);
}
+static void kgem_fixup_relocs(struct kgem *kgem, struct kgem_bo *bo, int shrink)
+{
+ int n;
+
+ bo->target_handle = kgem->has_handle_lut ? kgem->nexec : bo->handle;
+
+ assert(kgem->nreloc__self <= 256);
+ if (kgem->nreloc__self == 0)
+ return;
+
+ DBG(("%s: fixing up %d%s self-relocations to handle=%p, presumed-offset=%llx\n",
+ __FUNCTION__, kgem->nreloc__self,
+ kgem->nreloc__self == 256 ? "+" : "",
+ bo->handle, (long long)bo->presumed_offset));
+ for (n = 0; n < kgem->nreloc__self; n++) {
+ int i = kgem->reloc__self[n];
+
+ assert(kgem->reloc[i].target_handle == ~0U);
+ kgem->reloc[i].target_handle = bo->target_handle;
+ kgem->reloc[i].presumed_offset = bo->presumed_offset;
+
+ if (kgem->reloc[i].read_domains == I915_GEM_DOMAIN_INSTRUCTION) {
+ DBG(("%s: moving base of self-reloc[%d:%d] %d -> %d\n",
+ __FUNCTION__, n, i,
+ kgem->reloc[i].delta,
+ kgem->reloc[i].delta - shrink));
+
+ kgem->reloc[i].delta -= shrink;
+ }
+ kgem->batch[kgem->reloc[i].offset/sizeof(uint32_t)] =
+ kgem->reloc[i].delta + bo->presumed_offset;
+ }
+
+ if (n == 256) {
+ for (n = kgem->reloc__self[255]; n < kgem->nreloc; n++) {
+ if (kgem->reloc[n].target_handle == ~0U) {
+ kgem->reloc[n].target_handle = bo->target_handle;
+ kgem->reloc[n].presumed_offset = bo->presumed_offset;
+
+ if (kgem->reloc[n].read_domains == I915_GEM_DOMAIN_INSTRUCTION) {
+ DBG(("%s: moving base of reloc[%d] %d -> %d\n",
+ __FUNCTION__, n,
+ kgem->reloc[n].delta,
+ kgem->reloc[n].delta - shrink));
+ kgem->reloc[n].delta -= shrink;
+ }
+ kgem->batch[kgem->reloc[n].offset/sizeof(uint32_t)] =
+ kgem->reloc[n].delta + bo->presumed_offset;
+ }
+ }
+ }
+
+ if (shrink) {
+ DBG(("%s: shrinking by %d\n", __FUNCTION__, shrink));
+ for (n = 0; n < kgem->nreloc; n++) {
+ if (kgem->reloc[n].offset >= sizeof(uint32_t)*kgem->nbatch)
+ kgem->reloc[n].offset -= shrink;
+ }
+ }
+}
+
+static struct kgem_bo *kgem_new_batch(struct kgem *kgem)
+{
+ struct kgem_bo *last;
+ unsigned flags;
+
+ last = kgem->batch_bo;
+ if (last) {
+ kgem_fixup_relocs(kgem, last, 0);
+ kgem->batch = NULL;
+ }
+
+ if (kgem->batch) {
+ assert(last == NULL);
+ return NULL;
+ }
+
+ flags = CREATE_CPU_MAP | CREATE_NO_THROTTLE;
+ if (!kgem->has_llc)
+ flags |= CREATE_UNCACHED;
+
+ kgem->batch_bo = kgem_create_linear(kgem,
+ sizeof(uint32_t)*kgem->batch_size,
+ flags);
+ if (kgem->batch_bo)
+ kgem->batch = kgem_bo_map__cpu(kgem, kgem->batch_bo);
+ if (kgem->batch == NULL) {
+ DBG(("%s: unable to map batch bo, mallocing(size=%d)\n",
+ __FUNCTION__,
+ sizeof(uint32_t)*kgem->batch_size));
+ if (kgem->batch_bo) {
+ kgem_bo_destroy(kgem, kgem->batch_bo);
+ kgem->batch_bo = NULL;
+ }
+
+ if (posix_memalign((void **)&kgem->batch, PAGE_SIZE,
+ ALIGN(sizeof(uint32_t) * kgem->batch_size, PAGE_SIZE))) {
+ ERR(("%s: batch allocation failed, disabling acceleration\n", __FUNCTION__));
+ __kgem_set_wedged(kgem);
+ }
+ } else {
+ DBG(("%s: allocated and mapped batch handle=%d [size=%d]\n",
+ __FUNCTION__, kgem->batch_bo->handle,
+ sizeof(uint32_t)*kgem->batch_size));
+ kgem_bo_sync__cpu(kgem, kgem->batch_bo);
+ }
+
+ DBG(("%s: using last batch handle=%d\n",
+ __FUNCTION__, last ? last->handle : 0));
+ return last;
+}
void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
{
@@ -1316,6 +1562,10 @@ void kgem_init(struct kgem *kgem, int fd
DBG(("%s: has write-through caching for scanouts? %d\n", __FUNCTION__,
kgem->has_wt));
+ kgem->has_wc_mmap = test_has_wc_mmap(kgem);
+ DBG(("%s: has wc-mmapping? %d\n", __FUNCTION__,
+ kgem->has_wc_mmap));
+
kgem->has_caching = test_has_caching(kgem);
DBG(("%s: has set-cache-level? %d\n", __FUNCTION__,
kgem->has_caching));
@@ -1361,14 +1611,14 @@ void kgem_init(struct kgem *kgem, int fd
if (!is_hw_supported(kgem, dev)) {
xf86DrvMsg(kgem_get_screen_index(kgem), X_WARNING,
"Detected unsupported/dysfunctional hardware, disabling acceleration.\n");
- kgem->wedged = 1;
+ __kgem_set_wedged(kgem);
} else if (__kgem_throttle(kgem, false)) {
xf86DrvMsg(kgem_get_screen_index(kgem), X_WARNING,
"Detected a hung GPU, disabling acceleration.\n");
- kgem->wedged = 1;
+ __kgem_set_wedged(kgem);
}
- kgem->batch_size = ARRAY_SIZE(kgem->batch);
+ kgem->batch_size = UINT16_MAX & ~7;
if (gen == 020 && !kgem->has_pinned_batches)
/* Limited to what we can pin */
kgem->batch_size = 4*1024;
@@ -1383,11 +1633,12 @@ void kgem_init(struct kgem *kgem, int fd
if (!kgem_init_pinned_batches(kgem) && gen == 020) {
xf86DrvMsg(kgem_get_screen_index(kgem), X_WARNING,
"Unable to reserve memory for GPU, disabling acceleration.\n");
- kgem->wedged = 1;
+ __kgem_set_wedged(kgem);
}
DBG(("%s: maximum batch size? %d\n", __FUNCTION__,
kgem->batch_size));
+ kgem_new_batch(kgem);
kgem->half_cpu_cache_pages = cpu_cache_size() >> 13;
DBG(("%s: last-level cache size: %d bytes, threshold in pages: %d\n",
@@ -1556,6 +1807,8 @@ inline static uint32_t kgem_pitch_alignm
return 256;
if (flags & CREATE_SCANOUT)
return 64;
+ if (kgem->gen >= 0100)
+ return 32;
return 8;
}
@@ -1809,36 +2062,6 @@ static uint32_t kgem_end_batch(struct kg
return kgem->nbatch;
}
-static void kgem_fixup_self_relocs(struct kgem *kgem, struct kgem_bo *bo)
-{
- int n;
-
- assert(kgem->nreloc__self <= 256);
- if (kgem->nreloc__self == 0)
- return;
-
- for (n = 0; n < kgem->nreloc__self; n++) {
- int i = kgem->reloc__self[n];
- assert(kgem->reloc[i].target_handle == ~0U);
- kgem->reloc[i].target_handle = bo->target_handle;
- kgem->reloc[i].presumed_offset = bo->presumed_offset;
- kgem->batch[kgem->reloc[i].offset/sizeof(kgem->batch[0])] =
- kgem->reloc[i].delta + bo->presumed_offset;
- }
-
- if (n == 256) {
- for (n = kgem->reloc__self[255]; n < kgem->nreloc; n++) {
- if (kgem->reloc[n].target_handle == ~0U) {
- kgem->reloc[n].target_handle = bo->target_handle;
- kgem->reloc[n].presumed_offset = bo->presumed_offset;
- kgem->batch[kgem->reloc[n].offset/sizeof(kgem->batch[0])] =
- kgem->reloc[n].delta + bo->presumed_offset;
- }
- }
-
- }
-}
-
static void kgem_bo_binding_free(struct kgem *kgem, struct kgem_bo *bo)
{
struct kgem_bo_binding *b;
@@ -1892,17 +2115,23 @@ static void kgem_bo_free(struct kgem *kg
DBG(("%s: releasing %p:%p vma for handle=%d, count=%d\n",
__FUNCTION__, bo->map__gtt, bo->map__cpu,
- bo->handle, list_is_empty(&bo->vma) ? 0 : kgem->vma[bo->map__gtt == NULL].count));
+ bo->handle, list_is_empty(&bo->vma) ? 0 : kgem->vma[bo->map__gtt == NULL && bo->map__wc == NULL].count));
if (!list_is_empty(&bo->vma)) {
_list_del(&bo->vma);
- kgem->vma[bo->map__gtt == NULL].count--;
+ kgem->vma[bo->map__gtt == NULL && bo->map__wc == NULL].count--;
}
if (bo->map__gtt)
- munmap(MAP(bo->map__gtt), bytes(bo));
- if (bo->map__cpu)
+ munmap(bo->map__gtt, bytes(bo));
+ if (bo->map__wc) {
+ VG(VALGRIND_MAKE_MEM_NOACCESS(bo->map__wc, bytes(bo)));
+ munmap(bo->map__wc, bytes(bo));
+ }
+ if (bo->map__cpu) {
+ VG(VALGRIND_MAKE_MEM_NOACCESS(MAP(bo->map__cpu), bytes(bo)));
munmap(MAP(bo->map__cpu), bytes(bo));
+ }
_list_del(&bo->list);
_list_del(&bo->request);
@@ -1938,25 +2167,24 @@ inline static void kgem_bo_move_to_inact
if (bucket(bo) >= NUM_CACHE_BUCKETS) {
if (bo->map__gtt) {
- munmap(MAP(bo->map__gtt), bytes(bo));
+ munmap(bo->map__gtt, bytes(bo));
bo->map__gtt = NULL;
}
list_move(&bo->list, &kgem->large_inactive);
} else {
assert(bo->flush == false);
+ assert(list_is_empty(&bo->vma));
list_move(&bo->list, &kgem->inactive[bucket(bo)]);
- if (bo->map__gtt) {
- if (!kgem_bo_can_map(kgem, bo)) {
- munmap(MAP(bo->map__gtt), bytes(bo));
- bo->map__gtt = NULL;
- }
- if (bo->map__gtt) {
- list_add(&bo->vma, &kgem->vma[0].inactive[bucket(bo)]);
- kgem->vma[0].count++;
- }
+ if (bo->map__gtt && !kgem_bo_can_map(kgem, bo)) {
+ munmap(bo->map__gtt, bytes(bo));
+ bo->map__gtt = NULL;
+ }
+ if (bo->map__gtt || (bo->map__wc && !bo->tiling)) {
+ list_add(&bo->vma, &kgem->vma[0].inactive[bucket(bo)]);
+ kgem->vma[0].count++;
}
- if (bo->map__cpu && !bo->map__gtt) {
+ if (bo->map__cpu && list_is_empty(&bo->vma)) {
list_add(&bo->vma, &kgem->vma[1].inactive[bucket(bo)]);
kgem->vma[1].count++;
}
@@ -2004,9 +2232,9 @@ inline static void kgem_bo_remove_from_i
assert(bo->rq == NULL);
assert(bo->exec == NULL);
if (!list_is_empty(&bo->vma)) {
- assert(bo->map__gtt || bo->map__cpu);
+ assert(bo->map__gtt || bo->map__wc || bo->map__cpu);
list_del(&bo->vma);
- kgem->vma[bo->map__gtt == NULL].count--;
+ kgem->vma[bo->map__gtt == NULL && bo->map__wc == NULL].count--;
}
}
@@ -2446,6 +2674,9 @@ static bool __kgem_retire_rq(struct kgem
__FUNCTION__, rq->bo->handle));
assert(RQ(rq->bo->rq) == rq);
+ if (rq == kgem->fence[rq->ring])
+ kgem->fence[rq->ring] = NULL;
+
while (!list_is_empty(&rq->buffers)) {
struct kgem_bo *bo;
@@ -2471,6 +2702,7 @@ static bool __kgem_retire_rq(struct kgem
}
bo->domain = DOMAIN_NONE;
+ bo->gtt_dirty = false;
bo->rq = NULL;
if (bo->refcnt)
continue;
@@ -2576,24 +2808,72 @@ bool __kgem_ring_is_idle(struct kgem *kg
assert(ring < ARRAY_SIZE(kgem->requests));
assert(!list_is_empty(&kgem->requests[ring]));
+ rq = kgem->fence[ring];
+ if (rq) {
+ struct kgem_request *tmp;
+
+ if (__kgem_busy(kgem, rq->bo->handle)) {
+ DBG(("%s: last fence handle=%d still busy\n",
+ __FUNCTION__, rq->bo->handle));
+ return false;
+ }
+
+ do {
+ tmp = list_first_entry(&kgem->requests[ring],
+ struct kgem_request,
+ list);
+ assert(tmp->ring == ring);
+ __kgem_retire_rq(kgem, tmp);
+ } while (tmp != rq);
+
+ assert(kgem->fence[ring] == NULL);
+ if (list_is_empty(&kgem->requests[ring]))
+ return true;
+ }
+
rq = list_last_entry(&kgem->requests[ring],
struct kgem_request, list);
assert(rq->ring == ring);
if (__kgem_busy(kgem, rq->bo->handle)) {
DBG(("%s: last requests handle=%d still busy\n",
__FUNCTION__, rq->bo->handle));
+ kgem->fence[ring] = rq;
return false;
}
DBG(("%s: ring=%d idle (handle=%d)\n",
__FUNCTION__, ring, rq->bo->handle));
- kgem_retire__requests_ring(kgem, ring);
+ while (!list_is_empty(&kgem->requests[ring])) {
+ rq = list_first_entry(&kgem->requests[ring],
+ struct kgem_request,
+ list);
+ assert(rq->ring == ring);
+ __kgem_retire_rq(kgem, rq);
+ }
- assert(list_is_empty(&kgem->requests[ring]));
return true;
}
+void __kgem_retire_requests_upto(struct kgem *kgem, struct kgem_bo *bo)
+{
+ struct kgem_request *rq = bo->rq, *tmp;
+ struct list *requests = &kgem->requests[RQ_RING(rq) == I915_EXEC_BLT];
+
+ rq = RQ(rq);
+ assert(rq != &kgem->static_request);
+ if (rq == (struct kgem_request *)kgem) {
+ __kgem_bo_clear_busy(bo);
+ return;
+ }
+
+ do {
+ tmp = list_first_entry(requests, struct kgem_request, list);
+ assert(tmp->ring == rq->ring);
+ __kgem_retire_rq(kgem, tmp);
+ } while (tmp != rq);
+}
+
#if 0
static void kgem_commit__check_reloc(struct kgem *kgem)
{
@@ -2689,6 +2969,7 @@ static void kgem_commit(struct kgem *kge
assert(list_is_empty(&rq->buffers));
assert(rq->bo->map__gtt == NULL);
+ assert(rq->bo->map__wc == NULL);
assert(rq->bo->map__cpu == NULL);
gem_close(kgem->fd, rq->bo->handle);
kgem_cleanup_cache(kgem);
@@ -2696,6 +2977,10 @@ static void kgem_commit(struct kgem *kge
assert(rq->ring < ARRAY_SIZE(kgem->requests));
list_add_tail(&rq->list, &kgem->requests[rq->ring]);
kgem->need_throttle = kgem->need_retire = 1;
+
+ if (kgem->fence[rq->ring] == NULL &&
+ __kgem_busy(kgem, rq->bo->handle))
+ kgem->fence[rq->ring] = rq;
}
kgem->next_request = NULL;
@@ -2927,24 +3212,50 @@ static void kgem_cleanup(struct kgem *kg
kgem_close_inactive(kgem);
}
-static int kgem_batch_write(struct kgem *kgem, uint32_t handle, uint32_t size)
+static int
+kgem_batch_write(struct kgem *kgem,
+ struct kgem_bo *bo,
+ uint32_t size)
{
+ char *ptr;
int ret;
- ASSERT_IDLE(kgem, handle);
+ ASSERT_IDLE(kgem, bo->handle);
#if DBG_NO_EXEC
{
uint32_t batch[] = { MI_BATCH_BUFFER_END, 0};
- return gem_write(kgem->fd, handle, 0, sizeof(batch), batch);
+ return gem_write(kgem->fd, bo->handle, 0, sizeof(batch), batch);
}
#endif
-
+ assert(!bo->scanout);
retry:
+ ptr = NULL;
+ if (bo->domain == DOMAIN_CPU || kgem->has_llc) {
+ ptr = bo->map__cpu;
+ if (ptr == NULL)
+ ptr = __kgem_bo_map__cpu(kgem, bo);
+ } else if (kgem->has_wc_mmap) {
+ ptr = bo->map__wc;
+ if (ptr == NULL)
+ ptr = __kgem_bo_map__wc(kgem, bo);
+ }
+ if (ptr) {
+ memcpy(ptr, kgem->batch, sizeof(uint32_t)*kgem->nbatch);
+ if (kgem->surface != kgem->batch_size) {
+ ret = PAGE_ALIGN(sizeof(uint32_t) * kgem->batch_size);
+ ret -= sizeof(uint32_t) * kgem->surface;
+ ptr += size - ret;
+ memcpy(ptr, kgem->batch + kgem->surface,
+ (kgem->batch_size - kgem->surface)*sizeof(uint32_t));
+ }
+ return 0;
+ }
+
/* If there is no surface data, just upload the batch */
if (kgem->surface == kgem->batch_size) {
- if ((ret = gem_write__cachealigned(kgem->fd, handle,
+ if ((ret = gem_write__cachealigned(kgem->fd, bo->handle,
0, sizeof(uint32_t)*kgem->nbatch,
kgem->batch)) == 0)
return 0;
@@ -2955,7 +3266,7 @@ retry:
/* Are the batch pages conjoint with the surface pages? */
if (kgem->surface < kgem->nbatch + PAGE_SIZE/sizeof(uint32_t)) {
assert(size == PAGE_ALIGN(kgem->batch_size*sizeof(uint32_t)));
- if ((ret = gem_write__cachealigned(kgem->fd, handle,
+ if ((ret = gem_write__cachealigned(kgem->fd, bo->handle,
0, kgem->batch_size*sizeof(uint32_t),
kgem->batch)) == 0)
return 0;
@@ -2964,7 +3275,7 @@ retry:
}
/* Disjoint surface/batch, upload separately */
- if ((ret = gem_write__cachealigned(kgem->fd, handle,
+ if ((ret = gem_write__cachealigned(kgem->fd, bo->handle,
0, sizeof(uint32_t)*kgem->nbatch,
kgem->batch)))
goto expire;
@@ -2972,7 +3283,7 @@ retry:
ret = PAGE_ALIGN(sizeof(uint32_t) * kgem->batch_size);
ret -= sizeof(uint32_t) * kgem->surface;
assert(size-ret >= kgem->nbatch*sizeof(uint32_t));
- if (gem_write(kgem->fd, handle,
+ if (gem_write(kgem->fd, bo->handle,
size - ret, (kgem->batch_size - kgem->surface)*sizeof(uint32_t),
kgem->batch + kgem->surface))
goto expire;
@@ -2990,7 +3301,7 @@ expire:
goto retry;
ERR(("%s: failed to write batch (handle=%d): %d\n",
- __FUNCTION__, handle, -ret));
+ __FUNCTION__, bo->handle, -ret));
return ret;
}
@@ -3047,15 +3358,16 @@ void kgem_reset(struct kgem *kgem)
kgem->needs_reservation = false;
kgem->flush = 0;
kgem->batch_flags = kgem->batch_flags_base;
+ assert(kgem->batch);
kgem->next_request = __kgem_request_alloc(kgem);
kgem_sna_reset(kgem);
}
-static int compact_batch_surface(struct kgem *kgem)
+static int compact_batch_surface(struct kgem *kgem, int *shrink)
{
- int size, shrink, n;
+ int size, n;
if (!kgem->has_relaxed_delta)
return kgem->batch_size * sizeof(uint32_t);
@@ -3065,29 +3377,23 @@ static int compact_batch_surface(struct
size = n - kgem->surface + kgem->nbatch;
size = ALIGN(size, 1024);
- shrink = n - size;
- if (shrink) {
- DBG(("shrinking from %d to %d\n", kgem->batch_size, size));
-
- shrink *= sizeof(uint32_t);
- for (n = 0; n < kgem->nreloc; n++) {
- if (kgem->reloc[n].read_domains == I915_GEM_DOMAIN_INSTRUCTION &&
- kgem->reloc[n].target_handle == ~0U)
- kgem->reloc[n].delta -= shrink;
-
- if (kgem->reloc[n].offset >= sizeof(uint32_t)*kgem->nbatch)
- kgem->reloc[n].offset -= shrink;
- }
- }
-
+ *shrink = (n - size) * sizeof(uint32_t);
return size * sizeof(uint32_t);
}
static struct kgem_bo *
-kgem_create_batch(struct kgem *kgem, int size)
+kgem_create_batch(struct kgem *kgem)
{
+#if !DBG_NO_SHRINK_BATCHES
struct drm_i915_gem_set_domain set_domain;
struct kgem_bo *bo;
+ int shrink = 0;
+ int size;
+
+ if (kgem->surface != kgem->batch_size)
+ size = compact_batch_surface(kgem, &shrink);
+ else
+ size = kgem->nbatch * sizeof(uint32_t);
if (size <= 4096) {
bo = list_first_entry(&kgem->pinned_batches[0],
@@ -3097,10 +3403,12 @@ kgem_create_batch(struct kgem *kgem, int
out_4096:
assert(bo->refcnt > 0);
list_move_tail(&bo->list, &kgem->pinned_batches[0]);
- return kgem_bo_reference(bo);
+ bo = kgem_bo_reference(bo);
+ goto write;
}
if (!__kgem_busy(kgem, bo->handle)) {
+ assert(RQ(bo->rq)->bo == bo);
__kgem_retire_rq(kgem, RQ(bo->rq));
goto out_4096;
}
@@ -3114,7 +3422,8 @@ out_4096:
out_16384:
assert(bo->refcnt > 0);
list_move_tail(&bo->list, &kgem->pinned_batches[1]);
- return kgem_bo_reference(bo);
+ bo = kgem_bo_reference(bo);
+ goto write;
}
if (!__kgem_busy(kgem, bo->handle)) {
@@ -3126,14 +3435,14 @@ out_16384:
if (kgem->gen == 020) {
bo = kgem_create_linear(kgem, size, CREATE_CACHED | CREATE_TEMPORARY);
if (bo)
- return bo;
+ goto write;
/* Nothing available for reuse, rely on the kernel wa */
if (kgem->has_pinned_batches) {
bo = kgem_create_linear(kgem, size, CREATE_CACHED | CREATE_TEMPORARY);
if (bo) {
kgem->batch_flags &= ~LOCAL_I915_EXEC_IS_PINNED;
- return bo;
+ goto write;
}
}
@@ -3157,11 +3466,29 @@ out_16384:
kgem_retire(kgem);
assert(bo->rq == NULL);
- return kgem_bo_reference(bo);
+ bo = kgem_bo_reference(bo);
+ goto write;
}
}
- return kgem_create_linear(kgem, size, CREATE_NO_THROTTLE);
+ bo = NULL;
+ if (!kgem->has_llc) {
+ bo = kgem_create_linear(kgem, size, CREATE_NO_THROTTLE);
+ if (bo) {
+write:
+ kgem_fixup_relocs(kgem, bo, shrink);
+ if (kgem_batch_write(kgem, bo, size)) {
+ kgem_bo_destroy(kgem, bo);
+ return NULL;
+ }
+ }
+ }
+ if (bo == NULL)
+ bo = kgem_new_batch(kgem);
+ return bo;
+#else
+ return kgem_new_batch(kgem);
+#endif
}
#if !NDEBUG
@@ -3213,7 +3540,7 @@ static void dump_fence_regs(struct kgem
static int do_execbuf(struct kgem *kgem, struct drm_i915_gem_execbuffer2 *execbuf)
{
- int ret;
+ int ret, err;
retry:
ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
@@ -3229,14 +3556,35 @@ retry:
goto retry;
/* last gasp */
- return do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
+ ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
+ if (ret == 0)
+ return 0;
+
+ xf86DrvMsg(kgem_get_screen_index(kgem), X_WARNING,
+ "Failed to submit rendering commands, trying again with outputs disabled.\n");
+
+ /* One last trick up our sleeve for when we run out of space.
+ * We turn everything off to free up our pinned framebuffers,
+ * sprites and cursors, and try one last time.
+ */
+ err = errno;
+ if (sna_mode_disable(container_of(kgem, struct sna, kgem))) {
+ kgem_cleanup_cache(kgem);
+ ret = do_ioctl(kgem->fd,
+ DRM_IOCTL_I915_GEM_EXECBUFFER2,
+ execbuf);
+ DBG(("%s: last_gasp ret=%d\n", __FUNCTION__, ret));
+ sna_mode_enable(container_of(kgem, struct sna, kgem));
+ }
+ errno = err;
+
+ return ret;
}
void _kgem_submit(struct kgem *kgem)
{
struct kgem_request *rq;
uint32_t batch_end;
- int size;
assert(!DBG_NO_HW);
assert(!kgem->wedged);
@@ -3266,19 +3614,17 @@ void _kgem_submit(struct kgem *kgem)
#endif
rq = kgem->next_request;
- if (kgem->surface != kgem->batch_size)
- size = compact_batch_surface(kgem);
- else
- size = kgem->nbatch * sizeof(kgem->batch[0]);
- rq->bo = kgem_create_batch(kgem, size);
+ assert(rq->bo == NULL);
+
+ rq->bo = kgem_create_batch(kgem);
if (rq->bo) {
- uint32_t handle = rq->bo->handle;
- int i;
+ struct drm_i915_gem_execbuffer2 execbuf;
+ int i, ret;
assert(!rq->bo->needs_flush);
i = kgem->nexec++;
- kgem->exec[i].handle = handle;
+ kgem->exec[i].handle = rq->bo->handle;
kgem->exec[i].relocation_count = kgem->nreloc;
kgem->exec[i].relocs_ptr = (uintptr_t)kgem->reloc;
kgem->exec[i].alignment = 0;
@@ -3287,117 +3633,109 @@ void _kgem_submit(struct kgem *kgem)
kgem->exec[i].rsvd1 = 0;
kgem->exec[i].rsvd2 = 0;
- rq->bo->target_handle = kgem->has_handle_lut ? i : handle;
rq->bo->exec = &kgem->exec[i];
rq->bo->rq = MAKE_REQUEST(rq, kgem->ring); /* useful sanity check */
list_add(&rq->bo->request, &rq->buffers);
rq->ring = kgem->ring == KGEM_BLT;
- kgem_fixup_self_relocs(kgem, rq->bo);
-
- if (kgem_batch_write(kgem, handle, size) == 0) {
- struct drm_i915_gem_execbuffer2 execbuf;
- int ret;
-
- memset(&execbuf, 0, sizeof(execbuf));
- execbuf.buffers_ptr = (uintptr_t)kgem->exec;
- execbuf.buffer_count = kgem->nexec;
- execbuf.batch_len = batch_end*sizeof(uint32_t);
- execbuf.flags = kgem->ring | kgem->batch_flags;
-
- if (DBG_DUMP) {
- int fd = open("/tmp/i915-batchbuffers.dump",
- O_WRONLY | O_CREAT | O_APPEND,
- 0666);
- if (fd != -1) {
- ret = write(fd, kgem->batch, batch_end*sizeof(uint32_t));
- fd = close(fd);
- }
+ memset(&execbuf, 0, sizeof(execbuf));
+ execbuf.buffers_ptr = (uintptr_t)kgem->exec;
+ execbuf.buffer_count = kgem->nexec;
+ execbuf.batch_len = batch_end*sizeof(uint32_t);
+ execbuf.flags = kgem->ring | kgem->batch_flags;
+
+ if (DBG_DUMP) {
+ int fd = open("/tmp/i915-batchbuffers.dump",
+ O_WRONLY | O_CREAT | O_APPEND,
+ 0666);
+ if (fd != -1) {
+ ret = write(fd, kgem->batch, batch_end*sizeof(uint32_t));
+ fd = close(fd);
}
+ }
- ret = do_execbuf(kgem, &execbuf);
- if (DEBUG_SYNC && ret == 0) {
- struct drm_i915_gem_set_domain set_domain;
-
- VG_CLEAR(set_domain);
- set_domain.handle = handle;
- set_domain.read_domains = I915_GEM_DOMAIN_GTT;
- set_domain.write_domain = I915_GEM_DOMAIN_GTT;
+ ret = do_execbuf(kgem, &execbuf);
+ if (DEBUG_SYNC && ret == 0) {
+ struct drm_i915_gem_set_domain set_domain;
+
+ VG_CLEAR(set_domain);
+ set_domain.handle = rq->bo->handle;
+ set_domain.read_domains = I915_GEM_DOMAIN_GTT;
+ set_domain.write_domain = I915_GEM_DOMAIN_GTT;
- ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
+ ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
+ }
+ if (ret < 0) {
+ kgem_throttle(kgem);
+ if (!kgem->wedged) {
+ xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
+ "Failed to submit rendering commands, disabling acceleration.\n");
+ __kgem_set_wedged(kgem);
}
- if (ret < 0) {
- kgem_throttle(kgem);
- if (!kgem->wedged) {
- xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
- "Failed to submit rendering commands, disabling acceleration.\n");
- kgem->wedged = true;
- }
#if !NDEBUG
- ErrorF("batch[%d/%d]: %d %d %d, nreloc=%d, nexec=%d, nfence=%d, aperture=%d, fenced=%d, high=%d,%d: errno=%d\n",
- kgem->mode, kgem->ring, batch_end, kgem->nbatch, kgem->surface,
- kgem->nreloc, kgem->nexec, kgem->nfence, kgem->aperture, kgem->aperture_fenced, kgem->aperture_high, kgem->aperture_total, -ret);
-
- for (i = 0; i < kgem->nexec; i++) {
- struct kgem_bo *bo, *found = NULL;
-
- list_for_each_entry(bo, &kgem->next_request->buffers, request) {
- if (bo->handle == kgem->exec[i].handle) {
- found = bo;
- break;
- }
+ ErrorF("batch[%d/%d]: %d %d %d, nreloc=%d, nexec=%d, nfence=%d, aperture=%d, fenced=%d, high=%d,%d: errno=%d\n",
+ kgem->mode, kgem->ring, batch_end, kgem->nbatch, kgem->surface,
+ kgem->nreloc, kgem->nexec, kgem->nfence, kgem->aperture, kgem->aperture_fenced, kgem->aperture_high, kgem->aperture_total, -ret);
+
+ for (i = 0; i < kgem->nexec; i++) {
+ struct kgem_bo *bo, *found = NULL;
+
+ list_for_each_entry(bo, &kgem->next_request->buffers, request) {
+ if (bo->handle == kgem->exec[i].handle) {
+ found = bo;
+ break;
}
- ErrorF("exec[%d] = handle:%d, presumed offset: %x, size: %d, tiling %d, fenced %d, snooped %d, deleted %d\n",
- i,
- kgem->exec[i].handle,
- (int)kgem->exec[i].offset,
- found ? kgem_bo_size(found) : -1,
- found ? found->tiling : -1,
- (int)(kgem->exec[i].flags & EXEC_OBJECT_NEEDS_FENCE),
- found ? found->snoop : -1,
- found ? found->purged : -1);
- }
- for (i = 0; i < kgem->nreloc; i++) {
- ErrorF("reloc[%d] = pos:%d, target:%d, delta:%d, read:%x, write:%x, offset:%x\n",
- i,
- (int)kgem->reloc[i].offset,
- kgem->reloc[i].target_handle,
- kgem->reloc[i].delta,
- kgem->reloc[i].read_domains,
- kgem->reloc[i].write_domain,
- (int)kgem->reloc[i].presumed_offset);
}
+ ErrorF("exec[%d] = handle:%d, presumed offset: %x, size: %d, tiling %d, fenced %d, snooped %d, deleted %d\n",
+ i,
+ kgem->exec[i].handle,
+ (int)kgem->exec[i].offset,
+ found ? kgem_bo_size(found) : -1,
+ found ? found->tiling : -1,
+ (int)(kgem->exec[i].flags & EXEC_OBJECT_NEEDS_FENCE),
+ found ? found->snoop : -1,
+ found ? found->purged : -1);
+ }
+ for (i = 0; i < kgem->nreloc; i++) {
+ ErrorF("reloc[%d] = pos:%d, target:%d, delta:%d, read:%x, write:%x, offset:%x\n",
+ i,
+ (int)kgem->reloc[i].offset,
+ kgem->reloc[i].target_handle,
+ kgem->reloc[i].delta,
+ kgem->reloc[i].read_domains,
+ kgem->reloc[i].write_domain,
+ (int)kgem->reloc[i].presumed_offset);
+ }
+
+ {
+ struct drm_i915_gem_get_aperture aperture;
+ if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture) == 0)
+ ErrorF("Aperture size %lld, available %lld\n",
+ (long long)aperture.aper_size,
+ (long long)aperture.aper_available_size);
+ }
+
+ if (ret == -ENOSPC)
+ dump_gtt_info(kgem);
+ if (ret == -EDEADLK)
+ dump_fence_regs(kgem);
- {
- struct drm_i915_gem_get_aperture aperture;
- if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture) == 0)
- ErrorF("Aperture size %lld, available %lld\n",
- (long long)aperture.aper_size,
- (long long)aperture.aper_available_size);
+ if (DEBUG_SYNC) {
+ int fd = open("/tmp/batchbuffer", O_WRONLY | O_CREAT | O_APPEND, 0666);
+ if (fd != -1) {
+ int ignored = write(fd, kgem->batch, batch_end*sizeof(uint32_t));
+ assert(ignored == batch_end*sizeof(uint32_t));
+ close(fd);
}
- if (ret == -ENOSPC)
- dump_gtt_info(kgem);
- if (ret == -EDEADLK)
- dump_fence_regs(kgem);
-
- if (DEBUG_SYNC) {
- int fd = open("/tmp/batchbuffer", O_WRONLY | O_CREAT | O_APPEND, 0666);
- if (fd != -1) {
- int ignored = write(fd, kgem->batch, batch_end*sizeof(uint32_t));
- assert(ignored == batch_end*sizeof(uint32_t));
- close(fd);
- }
-
- FatalError("SNA: failed to submit batchbuffer, errno=%d\n", -ret);
- }
-#endif
+ FatalError("SNA: failed to submit batchbuffer, errno=%d\n", -ret);
}
+#endif
}
}
#if SHOW_BATCH_AFTER
- if (gem_read(kgem->fd, rq->bo->handle, kgem->batch, 0, batch_end*sizeof(uint32_t) == 0))
+ if (gem_read(kgem->fd, rq->bo->handle, kgem->batch, 0, batch_end*sizeof(uint32_t)) == 0)
__kgem_batch_debug(kgem, batch_end);
#endif
kgem_commit(kgem);
@@ -3439,8 +3777,7 @@ void kgem_throttle(struct kgem *kgem)
if (kgem->wedged)
return;
- kgem->wedged = __kgem_throttle(kgem, true);
- if (kgem->wedged) {
+ if (__kgem_throttle(kgem, true)) {
static int once;
char path[128];
@@ -3453,6 +3790,7 @@ void kgem_throttle(struct kgem *kgem)
once = 1;
}
+ __kgem_set_wedged(kgem);
kgem->need_throttle = false;
}
}
@@ -3823,7 +4161,7 @@ discard:
__FUNCTION__, for_cpu ? "cpu" : "gtt"));
cache = &kgem->vma[for_cpu].inactive[cache_bucket(num_pages)];
list_for_each_entry(bo, cache, vma) {
- assert(for_cpu ? bo->map__cpu : bo->map__gtt);
+ assert(for_cpu ? !!bo->map__cpu : (bo->map__gtt || bo->map__wc));
assert(bucket(bo) == cache_bucket(num_pages));
assert(bo->proxy == NULL);
assert(bo->rq == NULL);
@@ -3905,10 +4243,10 @@ discard:
bo->pitch = 0;
}
- if (bo->map__gtt || bo->map__cpu) {
+ if (bo->map__gtt || bo->map__wc || bo->map__cpu) {
if (flags & (CREATE_CPU_MAP | CREATE_GTT_MAP)) {
int for_cpu = !!(flags & CREATE_CPU_MAP);
- if (for_cpu ? bo->map__cpu : bo->map__gtt){
+ if (for_cpu ? !!bo->map__cpu : (bo->map__gtt || bo->map__wc)){
if (first != NULL)
break;
@@ -4148,16 +4486,18 @@ struct kgem_bo *kgem_create_linear(struc
}
size = NUM_PAGES(size);
- bo = search_linear_cache(kgem, size, CREATE_INACTIVE | flags);
- if (bo) {
- assert(bo->domain != DOMAIN_GPU);
- ASSERT_IDLE(kgem, bo->handle);
- bo->refcnt = 1;
- return bo;
- }
+ if ((flags & CREATE_UNCACHED) == 0) {
+ bo = search_linear_cache(kgem, size, CREATE_INACTIVE | flags);
+ if (bo) {
+ assert(bo->domain != DOMAIN_GPU);
+ ASSERT_IDLE(kgem, bo->handle);
+ bo->refcnt = 1;
+ return bo;
+ }
- if (flags & CREATE_CACHED)
- return NULL;
+ if (flags & CREATE_CACHED)
+ return NULL;
+ }
handle = gem_create(kgem->fd, size);
if (handle == 0)
@@ -4313,7 +4653,7 @@ unsigned kgem_can_create_2d(struct kgem
flags |= KGEM_CAN_CREATE_CPU;
if (size > 4096 && size <= kgem->max_gpu_size)
flags |= KGEM_CAN_CREATE_GPU;
- if (size <= PAGE_SIZE*kgem->aperture_mappable/4)
+ if (size <= PAGE_SIZE*kgem->aperture_mappable/4 || kgem->has_wc_mmap)
flags |= KGEM_CAN_CREATE_GTT;
if (size > kgem->large_object_size)
flags |= KGEM_CAN_CREATE_LARGE;
@@ -4465,7 +4805,10 @@ static void __kgem_bo_make_scanout(struc
if (bo->map__gtt == NULL)
bo->map__gtt = __kgem_bo_map__gtt(kgem, bo);
if (bo->map__gtt) {
- *(uint32_t *)bo->map__gtt = 0;
+ if (sigtrap_get() == 0) {
+ *(uint32_t *)bo->map__gtt = 0;
+ sigtrap_put();
+ }
bo->domain = DOMAIN_GTT;
}
@@ -4736,7 +5079,7 @@ large_inactive:
assert(bucket(bo) == bucket);
assert(bo->refcnt == 0);
assert(!bo->scanout);
- assert(for_cpu ? bo->map__cpu : bo->map__gtt);
+ assert(for_cpu ? !!bo->map__cpu : (bo->map__gtt || bo->map__wc));
assert(bo->rq == NULL);
assert(bo->exec == NULL);
assert(list_is_empty(&bo->request));
@@ -5192,6 +5535,7 @@ struct kgem_bo *kgem_create_cpu_2d(struc
assert(bo->tiling == I915_TILING_NONE);
assert_tiling(kgem, bo);
+ assert(!__kgem_busy(kgem, bo->handle));
if (!gem_set_caching(kgem->fd, bo->handle, SNOOPED)) {
kgem_bo_destroy(kgem, bo);
return NULL;
@@ -5828,7 +6172,6 @@ static void kgem_trim_vma_cache(struct k
i = 0;
while (kgem->vma[type].count > 0) {
struct kgem_bo *bo = NULL;
- void **ptr;
for (j = 0;
bo == NULL && j < ARRAY_SIZE(kgem->vma[type].inactive);
@@ -5843,12 +6186,23 @@ static void kgem_trim_vma_cache(struct k
DBG(("%s: discarding inactive %s vma cache for %d\n",
__FUNCTION__, type ? "CPU" : "GTT", bo->handle));
- ptr = type ? &bo->map__cpu : &bo->map__gtt;
assert(bo->rq == NULL);
+ if (type) {
+ VG(VALGRIND_MAKE_MEM_NOACCESS(MAP(bo->map__cpu), bytes(bo)));
+ munmap(MAP(bo->map__cpu), bytes(bo));
+ bo->map__cpu = NULL;
+ } else {
+ if (bo->map__wc) {
+ VG(VALGRIND_MAKE_MEM_NOACCESS(bo->map__wc, bytes(bo)));
+ munmap(bo->map__wc, bytes(bo));
+ bo->map__wc = NULL;
+ }
+ if (bo->map__gtt) {
+ munmap(bo->map__gtt, bytes(bo));
+ bo->map__gtt = NULL;
+ }
+ }
- VG(if (type) VALGRIND_MAKE_MEM_NOACCESS(MAP(*ptr), bytes(bo)));
- munmap(MAP(*ptr), bytes(bo));
- *ptr = NULL;
list_del(&bo->vma);
kgem->vma[type].count--;
@@ -5860,10 +6214,35 @@ static void kgem_trim_vma_cache(struct k
}
}
-void *kgem_bo_map__async(struct kgem *kgem, struct kgem_bo *bo)
+static void *__kgem_bo_map__gtt_or_wc(struct kgem *kgem, struct kgem_bo *bo)
{
void *ptr;
+ DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
+
+ assert(bo->proxy == NULL);
+ assert(!bo->snoop);
+
+ kgem_trim_vma_cache(kgem, MAP_GTT, bucket(bo));
+
+ if (bo->tiling || !kgem->has_wc_mmap) {
+ assert(num_pages(bo) <= kgem->aperture_mappable / 2);
+ assert(kgem->gen != 021 || bo->tiling != I915_TILING_Y);
+
+ ptr = bo->map__gtt;
+ if (ptr == NULL)
+ ptr = __kgem_bo_map__gtt(kgem, bo);
+ } else {
+ ptr = bo->map__wc;
+ if (ptr == NULL)
+ ptr = __kgem_bo_map__wc(kgem, bo);
+ }
+
+ return ptr;
+}
+
+void *kgem_bo_map__async(struct kgem *kgem, struct kgem_bo *bo)
+{
DBG(("%s: handle=%d, offset=%ld, tiling=%d, map=%p:%p, domain=%d\n", __FUNCTION__,
bo->handle, (long)bo->presumed_offset, bo->tiling, bo->map__gtt, bo->map__cpu, bo->domain));
@@ -5878,26 +6257,7 @@ void *kgem_bo_map__async(struct kgem *kg
return kgem_bo_map__cpu(kgem, bo);
}
- ptr = MAP(bo->map__gtt);
- if (ptr == NULL) {
- assert(num_pages(bo) <= kgem->aperture_mappable / 2);
-
- kgem_trim_vma_cache(kgem, MAP_GTT, bucket(bo));
-
- ptr = __kgem_bo_map__gtt(kgem, bo);
- if (ptr == NULL)
- return NULL;
-
- /* Cache this mapping to avoid the overhead of an
- * excruciatingly slow GTT pagefault. This is more an
- * issue with compositing managers which need to frequently
- * flush CPU damage to their GPU bo.
- */
- bo->map__gtt = ptr;
- DBG(("%s: caching GTT vma for %d\n", __FUNCTION__, bo->handle));
- }
-
- return ptr;
+ return __kgem_bo_map__gtt_or_wc(kgem, bo);
}
void *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo)
@@ -5923,25 +6283,7 @@ void *kgem_bo_map(struct kgem *kgem, str
return ptr;
}
- ptr = MAP(bo->map__gtt);
- if (ptr == NULL) {
- assert(num_pages(bo) <= kgem->aperture_mappable / 2);
- assert(kgem->gen != 021 || bo->tiling != I915_TILING_Y);
-
- kgem_trim_vma_cache(kgem, MAP_GTT, bucket(bo));
-
- ptr = __kgem_bo_map__gtt(kgem, bo);
- if (ptr == NULL)
- return NULL;
-
- /* Cache this mapping to avoid the overhead of an
- * excruciatingly slow GTT pagefault. This is more an
- * issue with compositing managers which need to frequently
- * flush CPU damage to their GPU bo.
- */
- bo->map__gtt = ptr;
- DBG(("%s: caching GTT vma for %d\n", __FUNCTION__, bo->handle));
- }
+ ptr = __kgem_bo_map__gtt_or_wc(kgem, bo);
if (bo->domain != DOMAIN_GTT || FORCE_MMAP_SYNC & (1 << DOMAIN_GTT)) {
struct drm_i915_gem_set_domain set_domain;
@@ -5969,8 +6311,6 @@ void *kgem_bo_map(struct kgem *kgem, str
void *kgem_bo_map__gtt(struct kgem *kgem, struct kgem_bo *bo)
{
- void *ptr;
-
DBG(("%s: handle=%d, offset=%ld, tiling=%d, map=%p:%p, domain=%d\n", __FUNCTION__,
bo->handle, (long)bo->presumed_offset, bo->tiling, bo->map__gtt, bo->map__cpu, bo->domain));
@@ -5980,38 +6320,28 @@ void *kgem_bo_map__gtt(struct kgem *kgem
assert_tiling(kgem, bo);
assert(!bo->purged || bo->reusable);
- ptr = MAP(bo->map__gtt);
- if (ptr == NULL) {
- assert(num_pages(bo) <= kgem->aperture_mappable / 4);
-
- kgem_trim_vma_cache(kgem, MAP_GTT, bucket(bo));
+ return __kgem_bo_map__gtt_or_wc(kgem, bo);
+}
- ptr = __kgem_bo_map__gtt(kgem, bo);
- if (ptr == NULL)
- return NULL;
+void *kgem_bo_map__wc(struct kgem *kgem, struct kgem_bo *bo)
+{
+ DBG(("%s: handle=%d, offset=%ld, tiling=%d, map=%p:%p, domain=%d\n", __FUNCTION__,
+ bo->handle, (long)bo->presumed_offset, bo->tiling, bo->map__gtt, bo->map__cpu, bo->domain));
- /* Cache this mapping to avoid the overhead of an
- * excruciatingly slow GTT pagefault. This is more an
- * issue with compositing managers which need to frequently
- * flush CPU damage to their GPU bo.
- */
- bo->map__gtt = ptr;
- DBG(("%s: caching GTT vma for %d\n", __FUNCTION__, bo->handle));
- }
+ assert(bo->proxy == NULL);
+ assert(bo->exec == NULL);
+ assert(list_is_empty(&bo->list));
+ assert_tiling(kgem, bo);
+ assert(!bo->purged || bo->reusable);
- return ptr;
-}
+ if (bo->map__wc)
+ return bo->map__wc;
-void *kgem_bo_map__debug(struct kgem *kgem, struct kgem_bo *bo)
-{
- return kgem_bo_map__async(kgem, bo);
+ return __kgem_bo_map__wc(kgem, bo);
}
void *kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo)
{
- struct drm_i915_gem_mmap mmap_arg;
- int err;
-
DBG(("%s(handle=%d, size=%d, map=%p:%p)\n",
__FUNCTION__, bo->handle, bytes(bo), bo->map__gtt, bo->map__cpu));
assert(!bo->purged);
@@ -6024,31 +6354,31 @@ void *kgem_bo_map__cpu(struct kgem *kgem
kgem_trim_vma_cache(kgem, MAP_CPU, bucket(bo));
-retry:
- VG_CLEAR(mmap_arg);
- mmap_arg.handle = bo->handle;
- mmap_arg.offset = 0;
- mmap_arg.size = bytes(bo);
- if ((err = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg))) {
- assert(err != EINVAL);
-
- if (__kgem_throttle_retire(kgem, 0))
- goto retry;
+ return __kgem_bo_map__cpu(kgem, bo);
+}
- if (kgem_cleanup_cache(kgem))
- goto retry;
+void *kgem_bo_map__debug(struct kgem *kgem, struct kgem_bo *bo)
+{
+ void *ptr;
- ERR(("%s: failed to mmap handle=%d, %d bytes, into CPU domain: %d\n",
- __FUNCTION__, bo->handle, bytes(bo), -err));
- return NULL;
+ if (bo->tiling == I915_TILING_NONE && kgem->has_llc) {
+ ptr = MAP(bo->map__cpu);
+ if (ptr == NULL)
+ ptr = __kgem_bo_map__cpu(kgem, bo);
+ } else if (bo->tiling || !kgem->has_wc_mmap) {
+ ptr = bo->map__gtt;
+ if (ptr == NULL)
+ ptr = __kgem_bo_map__gtt(kgem, bo);
+ } else {
+ ptr = bo->map__wc;
+ if (ptr == NULL)
+ ptr = __kgem_bo_map__wc(kgem, bo);
}
- VG(VALGRIND_MAKE_MEM_DEFINED(mmap_arg.addr_ptr, bytes(bo)));
-
- DBG(("%s: caching CPU vma for %d\n", __FUNCTION__, bo->handle));
- return bo->map__cpu = (void *)(uintptr_t)mmap_arg.addr_ptr;
+ return ptr;
}
+
uint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo)
{
struct drm_gem_flink flink;
@@ -6344,6 +6674,7 @@ init_buffer_from_bo(struct kgem_buffer *
__FUNCTION__, old->handle));
assert(old->proxy == NULL);
+ assert(list_is_empty(&old->list));
memcpy(&bo->base, old, sizeof(*old));
if (old->rq)
@@ -6469,6 +6800,7 @@ create_snoopable_buffer(struct kgem *kge
assert(bo->base.refcnt == 1);
assert(bo->mmapped == MMAPPED_CPU);
assert(bo->need_io == false);
+ assert(!__kgem_busy(kgem, bo->base.handle));
if (!gem_set_caching(kgem->fd, bo->base.handle, SNOOPED))
goto free_caching;
@@ -6648,7 +6980,7 @@ struct kgem_bo *kgem_create_buffer(struc
assert(alloc);
alloc /= PAGE_SIZE;
- if (alloc > kgem->aperture_mappable / 4)
+ if (alloc > kgem->aperture_mappable / 4 && !kgem->has_wc_mmap)
flags &= ~KGEM_BUFFER_INPLACE;
if (kgem->has_llc &&
@@ -6880,7 +7212,7 @@ init:
assert(!bo->need_io || !bo->base.needs_flush);
assert(!bo->need_io || bo->base.domain != DOMAIN_GPU);
assert(bo->mem);
- assert(bo->mmapped != MMAPPED_GTT || MAP(bo->base.map__gtt) == bo->mem);
+ assert(bo->mmapped != MMAPPED_GTT || bo->base.map__gtt == bo->mem || bo->base.map__wc == bo->mem);
assert(bo->mmapped != MMAPPED_CPU || MAP(bo->base.map__cpu) == bo->mem);
bo->used = size;
@@ -6918,7 +7250,7 @@ struct kgem_bo *kgem_create_buffer_2d(st
assert(width > 0 && height > 0);
assert(ret != NULL);
stride = ALIGN(width, 2) * bpp >> 3;
- stride = ALIGN(stride, 4);
+ stride = ALIGN(stride, kgem->gen >= 0100 ? 32 : 4);
DBG(("%s: %dx%d, %d bpp, stride=%d\n",
__FUNCTION__, width, height, bpp, stride));
@@ -7227,7 +7559,8 @@ bool kgem_bo_convert_to_gpu(struct kgem
struct kgem_bo *bo,
unsigned flags)
{
- DBG(("%s: converting handle=%d from CPU to GPU, flags=%x\n", __FUNCTION__, bo->handle));
+ DBG(("%s: converting handle=%d from CPU to GPU, flags=%x, busy?=%d\n",
+ __FUNCTION__, bo->handle, flags, __kgem_bo_is_busy(kgem, bo)));
assert(bo->tiling == I915_TILING_NONE);
if (kgem->has_llc)
Index: xsrc/external/mit/xf86-video-intel/dist/src/sna/sna_display.c
diff -u xsrc/external/mit/xf86-video-intel/dist/src/sna/sna_display.c:1.2 xsrc/external/mit/xf86-video-intel/dist/src/sna/sna_display.c:1.3
--- xsrc/external/mit/xf86-video-intel/dist/src/sna/sna_display.c:1.2 Wed Nov 5 19:54:00 2014
+++ xsrc/external/mit/xf86-video-intel/dist/src/sna/sna_display.c Fri Jan 16 21:32:11 2015
@@ -120,16 +120,21 @@ struct sna_crtc {
int dpms_mode;
PixmapPtr slave_pixmap;
DamagePtr slave_damage;
- struct kgem_bo *bo, *shadow_bo;
+ struct kgem_bo *bo, *shadow_bo, *client_bo;
struct sna_cursor *cursor;
unsigned int last_cursor_size;
uint32_t offset;
bool shadow;
bool fallback_shadow;
bool transform;
+ bool flip_pending;
uint8_t id;
uint8_t pipe;
+ RegionRec client_damage; /* XXX overlap with shadow damage? */
+
+ uint16_t shadow_bo_width, shadow_bo_height;
+
uint32_t rotation;
struct plane {
uint32_t id;
@@ -215,6 +220,11 @@ enum { /* XXX copied from hw/xfree86/mod
static void sna_crtc_disable_cursor(struct sna *sna, struct sna_crtc *crtc);
+static bool is_zaphod(ScrnInfoPtr scrn)
+{
+ return xf86IsEntityShared(scrn->entityList[0]);
+}
+
inline static unsigned count_to_mask(int x)
{
return (1 << x) - 1;
@@ -245,15 +255,6 @@ static inline bool event_pending(int fd)
return poll(&pfd, 1, 0) == 1;
}
-static bool sna_mode_has_pending_events(struct sna *sna)
-{
- /* In order to workaround a kernel bug in not honouring O_NONBLOCK,
- * check that the fd is readable before attempting to read the next
- * event from drm.
- */
- return event_pending(sna->kgem.fd);
-}
-
static bool sna_mode_wait_for_event(struct sna *sna)
{
struct pollfd pfd;
@@ -603,24 +604,31 @@ static void sna_backlight_drain_uevents(
static void sna_backlight_close(struct sna *sna) { }
#endif
+static void
+sna_output_backlight_disable(struct sna_output *sna_output)
+{
+ xf86OutputPtr output = sna_output->base;
+
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "Failed to set backlight %s for output %s, disabling\n",
+ sna_output->backlight.iface, output->name);
+ backlight_disable(&sna_output->backlight);
+ if (output->randr_output) {
+ RRDeleteOutputProperty(output->randr_output, backlight_atom);
+ RRDeleteOutputProperty(output->randr_output, backlight_deprecated_atom);
+ }
+}
+
static int
sna_output_backlight_set(struct sna_output *sna_output, int level)
{
- xf86OutputPtr output = sna_output->base;
int ret = 0;
DBG(("%s(%s) level=%d, max=%d\n", __FUNCTION__,
- output->name, level, sna_output->backlight.max));
+ sna_output->base->name, level, sna_output->backlight.max));
if (backlight_set(&sna_output->backlight, level)) {
- xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
- "Failed to set backlight %s for output %s to brightness level %d, disabling\n",
- sna_output->backlight.iface, output->name, level);
- backlight_disable(&sna_output->backlight);
- if (output->randr_output) {
- RRDeleteOutputProperty(output->randr_output, backlight_atom);
- RRDeleteOutputProperty(output->randr_output, backlight_deprecated_atom);
- }
+ sna_output_backlight_disable(sna_output);
ret = -1;
}
@@ -628,10 +636,28 @@ sna_output_backlight_set(struct sna_outp
* the change latter when we wake up and the output is in a different
* state.
*/
- sna_backlight_drain_uevents(to_sna(output->scrn));
+ sna_backlight_drain_uevents(to_sna(sna_output->base->scrn));
return ret;
}
+static void
+sna_output_backlight_off(struct sna_output *sna_output)
+{
+ DBG(("%s(%s)\n", __FUNCTION__, sna_output->base->name));
+ backlight_off(&sna_output->backlight);
+ sna_output_backlight_set(sna_output, 0);
+}
+
+static void
+sna_output_backlight_on(struct sna_output *sna_output)
+{
+ DBG(("%s(%s)\n", __FUNCTION__, sna_output->base->name));
+ sna_output_backlight_set(sna_output,
+ sna_output->backlight_active_level);
+ if (backlight_on(&sna_output->backlight) < 0)
+ sna_output_backlight_disable(sna_output);
+}
+
static int
sna_output_backlight_get(xf86OutputPtr output)
{
@@ -916,6 +942,7 @@ rotation_set(struct sna *sna, struct pla
assert(p->id);
assert(p->rotation.prop);
+ VG_CLEAR(prop);
prop.obj_id = p->id;
prop.obj_type = LOCAL_MODE_OBJECT_PLANE;
prop.prop_id = p->rotation.prop;
@@ -962,6 +989,11 @@ sna_crtc_apply(xf86CrtcPtr crtc)
int i;
DBG(("%s CRTC:%d [pipe=%d], handle=%d\n", __FUNCTION__, sna_crtc->id, sna_crtc->pipe, sna_crtc->bo->handle));
+ if (!sna_crtc->kmode.clock) {
+ ERR(("%s(CRTC:%d [pipe=%d]): attempted to set an invalid mode\n",
+ __FUNCTION__, sna_crtc->id, sna_crtc->pipe));
+ return false;
+ }
assert(sna->mode.num_real_output < ARRAY_SIZE(output_ids));
sna_crtc_disable_cursor(sna, sna_crtc);
@@ -1003,14 +1035,21 @@ sna_crtc_apply(xf86CrtcPtr crtc)
(uint32_t)output->possible_clones));
assert(output->possible_crtcs & (1 << sna_crtc->pipe) ||
- xf86IsEntityShared(crtc->scrn->entityList[0]));
+ is_zaphod(crtc->scrn));
output_ids[output_count] = to_connector_id(output);
if (++output_count == ARRAY_SIZE(output_ids)) {
+ DBG(("%s: too many outputs (%d) for me!\n",
+ __FUNCTION__, output_count));
errno = EINVAL;
return false;
}
}
+ if (output_count == 0) {
+ DBG(("%s: no outputs\n", __FUNCTION__));
+ errno = EINVAL;
+ return false;
+ }
VG_CLEAR(arg);
arg.crtc_id = sna_crtc->id;
@@ -1070,6 +1109,7 @@ static bool wait_for_shadow(struct sna *
PixmapPtr pixmap = priv->pixmap;
DamagePtr damage;
struct kgem_bo *bo, *tmp;
+ int flip_active;
bool ret = true;
DBG(("%s: flags=%x, flips=%d, handle=%d, shadow=%d\n",
@@ -1084,14 +1124,13 @@ static bool wait_for_shadow(struct sna *
if ((flags & MOVE_WRITE) == 0) {
if ((flags & __MOVE_SCANOUT) == 0) {
- while (!list_is_empty(&sna->mode.shadow_crtc)) {
- struct sna_crtc *crtc =
- list_first_entry(&sna->mode.shadow_crtc,
- struct sna_crtc,
- shadow_link);
+ struct sna_crtc *crtc;
+
+ list_for_each_entry(crtc, &sna->mode.shadow_crtc, shadow_link) {
if (overlap(&sna->mode.shadow_region.extents,
&crtc->base->bounds)) {
DrawableRec draw;
+ RegionRec region;
draw.width = crtc->base->mode.HDisplay;
draw.height = crtc->base->mode.VDisplay;
@@ -1104,18 +1143,18 @@ static bool wait_for_shadow(struct sna *
crtc->base->bounds.y1,
crtc->base->bounds.x2,
crtc->base->bounds.y2,
- crtc->shadow_bo->handle));
+ crtc->client_bo->handle));
ret &= sna->render.copy_boxes(sna, GXcopy,
- &draw, crtc->shadow_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
+ &draw, crtc->client_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
&pixmap->drawable, priv->gpu_bo, 0, 0,
&crtc->base->bounds, 1,
0);
- }
- kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
- crtc->shadow_bo = NULL;
- list_del(&crtc->shadow_link);
+ region.extents = crtc->base->bounds;
+ region.data = NULL;
+ RegionSubtract(&sna->mode.shadow_region, &sna->mode.shadow_region, ®ion);
+ }
}
}
@@ -1127,17 +1166,32 @@ static bool wait_for_shadow(struct sna *
damage = sna->mode.shadow_damage;
sna->mode.shadow_damage = NULL;
- if (sna->mode.flip_active) {
+ flip_active = sna->mode.flip_active;
+ if (flip_active) {
+ struct sna_crtc *crtc;
+ list_for_each_entry(crtc, &sna->mode.shadow_crtc, shadow_link)
+ flip_active -= crtc->flip_pending;
+ DBG(("%s: %d flips still pending, shadow flip_active=%d\n",
+ __FUNCTION__, sna->mode.flip_active, flip_active));
+ }
+ if (flip_active) {
/* raw cmd to avoid setting wedged in the middle of an op */
drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_THROTTLE, 0);
sna->kgem.need_throttle = false;
- while (sna->mode.flip_active && sna_mode_has_pending_events(sna))
- sna_mode_wakeup(sna);
+ while (flip_active && sna_mode_wakeup(sna)) {
+ struct sna_crtc *crtc;
+
+ flip_active = sna->mode.flip_active;
+ list_for_each_entry(crtc, &sna->mode.shadow_crtc, shadow_link)
+ flip_active -= crtc->flip_pending;
+ }
+ DBG(("%s: after waiting %d flips outstanding, flip_active=%d\n",
+ __FUNCTION__, sna->mode.flip_active, flip_active));
}
bo = sna->mode.shadow;
- if (sna->mode.flip_active) {
+ if (flip_active) {
bo = kgem_create_2d(&sna->kgem,
pixmap->drawable.width,
pixmap->drawable.height,
@@ -1209,10 +1263,10 @@ static bool wait_for_shadow(struct sna *
crtc->base->bounds.y1,
crtc->base->bounds.x2,
crtc->base->bounds.y2,
- crtc->shadow_bo->handle));
+ crtc->client_bo->handle));
ret = sna->render.copy_boxes(sna, GXcopy,
- &draw, crtc->shadow_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
+ &draw, crtc->client_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
&pixmap->drawable, bo, 0, 0,
&crtc->base->bounds, 1,
0);
@@ -1223,8 +1277,8 @@ static bool wait_for_shadow(struct sna *
RegionSubtract(&sna->mode.shadow_region, &sna->mode.shadow_region, ®ion);
}
- kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
- crtc->shadow_bo = NULL;
+ kgem_bo_destroy(&sna->kgem, crtc->client_bo);
+ crtc->client_bo = NULL;
list_del(&crtc->shadow_link);
}
@@ -1416,7 +1470,7 @@ static bool sna_crtc_enable_shadow(struc
static void sna_crtc_disable_override(struct sna *sna, struct sna_crtc *crtc)
{
- if (crtc->shadow_bo == NULL)
+ if (crtc->client_bo == NULL)
return;
if (!crtc->transform) {
@@ -1428,13 +1482,13 @@ static void sna_crtc_disable_override(st
tmp.bitsPerPixel = sna->front->drawable.bitsPerPixel;
sna->render.copy_boxes(sna, GXcopy,
- &tmp, crtc->shadow_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
+ &tmp, crtc->client_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
&sna->front->drawable, __sna_pixmap_get_bo(sna->front), 0, 0,
&crtc->base->bounds, 1, 0);
list_del(&crtc->shadow_link);
}
- kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
- crtc->shadow_bo = NULL;
+ kgem_bo_destroy(&sna->kgem, crtc->client_bo);
+ crtc->client_bo = NULL;
}
static void sna_crtc_disable_shadow(struct sna *sna, struct sna_crtc *crtc)
@@ -1462,24 +1516,8 @@ static void sna_crtc_disable_shadow(stru
}
static void
-sna_crtc_disable(xf86CrtcPtr crtc)
+__sna_crtc_disable(struct sna *sna, struct sna_crtc *sna_crtc)
{
- struct sna *sna = to_sna(crtc->scrn);
- struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
- struct drm_mode_crtc arg;
-
- if (sna_crtc == NULL)
- return;
-
- DBG(("%s: disabling crtc [%d, pipe=%d]\n", __FUNCTION__,
- sna_crtc->id, sna_crtc->pipe));
-
- sna_crtc_force_outputs_off(crtc);
-
- memset(&arg, 0, sizeof(arg));
- arg.crtc_id = sna_crtc->id;
- (void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg);
-
sna_crtc->mode_serial++;
sna_crtc_disable_cursor(sna, sna_crtc);
@@ -1498,17 +1536,45 @@ sna_crtc_disable(xf86CrtcPtr crtc)
sna->mode.dirty = true;
}
+ if (sna_crtc->shadow_bo) {
+ kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
+ sna_crtc->shadow_bo = NULL;
+ }
sna_crtc->transform = false;
- assert(sna_crtc->dpms_mode == DPMSModeOff);
assert(!sna_crtc->shadow);
}
+static void
+sna_crtc_disable(xf86CrtcPtr crtc)
+{
+ struct sna *sna = to_sna(crtc->scrn);
+ struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+ struct drm_mode_crtc arg;
+
+ if (sna_crtc == NULL)
+ return;
+
+ DBG(("%s: disabling crtc [%d, pipe=%d]\n", __FUNCTION__,
+ sna_crtc->id, sna_crtc->pipe));
+
+ sna_crtc_force_outputs_off(crtc);
+ assert(sna_crtc->dpms_mode == DPMSModeOff);
+
+ memset(&arg, 0, sizeof(arg));
+ arg.crtc_id = sna_crtc->id;
+ (void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg);
+
+ __sna_crtc_disable(sna, sna_crtc);
+}
+
static void update_flush_interval(struct sna *sna)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
int i, max_vrefresh = 0;
+ DBG(("%s: front_active=%d\n", __FUNCTION__, sna->mode.front_active));
+
for (i = 0; i < sna->mode.num_real_crtc; i++) {
xf86CrtcPtr crtc = config->crtc[i];
@@ -1590,8 +1656,9 @@ void sna_copy_fbcon(struct sna *sna)
DBG(("%s\n", __FUNCTION__));
assert((sna->flags & SNA_IS_HOSTED) == 0);
- priv = sna_pixmap(sna->front);
- assert(priv && priv->gpu_bo);
+ priv = sna_pixmap_move_to_gpu(sna->front, MOVE_WRITE | __MOVE_SCANOUT);
+ if (priv == NULL)
+ return;
/* Scan the connectors for a framebuffer and assume that is the fbcon */
VG_CLEAR(fbcon);
@@ -1676,7 +1743,7 @@ static bool use_shadow(struct sna *sna,
RRTransformPtr transform;
PictTransform crtc_to_fb;
struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc;
- unsigned long pitch_limit;
+ unsigned pitch_limit;
struct sna_pixmap *priv;
BoxRec b;
@@ -1693,7 +1760,7 @@ static bool use_shadow(struct sna *sna,
}
if (sna->flags & SNA_TEAR_FREE && to_sna_crtc(crtc)->slave_pixmap) {
- DBG(("%s: tear-free shadow required\n", __FUNCTION__));
+ DBG(("%s: TearFree shadow required\n", __FUNCTION__));
return true;
}
@@ -1706,7 +1773,7 @@ static bool use_shadow(struct sna *sna,
return true;
}
- priv = sna_pixmap_force_to_gpu(sna->front, MOVE_READ);
+ priv = sna_pixmap_force_to_gpu(sna->front, MOVE_READ | __MOVE_SCANOUT);
if (priv == NULL)
return true; /* maybe we can create a bo for the scanout? */
@@ -1798,6 +1865,61 @@ static void set_shadow(struct sna *sna,
priv->move_to_gpu_data = sna;
}
+static struct kgem_bo *
+get_scanout_bo(struct sna *sna, PixmapPtr pixmap)
+{
+ struct sna_pixmap *priv;
+
+ priv = sna_pixmap_force_to_gpu(pixmap, MOVE_READ | __MOVE_SCANOUT);
+ if (!priv)
+ return NULL;
+
+ if (priv->gpu_bo->pitch & 63) {
+ struct kgem_bo *tmp;
+ BoxRec b;
+
+ DBG(("%s: converting to scanout bo due to bad pitch [%d]\n",
+ __FUNCTION__, priv->gpu_bo->pitch));
+
+ if (priv->pinned) {
+ DBG(("%s: failed as the Pixmap is already pinned [%x]\n",
+ __FUNCTION__, priv->pinned));
+ return NULL;
+ }
+
+ tmp = kgem_create_2d(&sna->kgem,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ sna->scrn->bitsPerPixel,
+ priv->gpu_bo->tiling,
+ CREATE_EXACT | CREATE_SCANOUT);
+ if (tmp == NULL) {
+ DBG(("%s: allocation failed\n", __FUNCTION__));
+ return NULL;
+ }
+
+ b.x1 = 0;
+ b.y1 = 0;
+ b.x2 = pixmap->drawable.width;
+ b.y2 = pixmap->drawable.height;
+
+ if (sna->render.copy_boxes(sna, GXcopy,
+ &pixmap->drawable, priv->gpu_bo, 0, 0,
+ &pixmap->drawable, tmp, 0, 0,
+ &b, 1, COPY_LAST)) {
+ DBG(("%s: copy failed\n", __FUNCTION__));
+ kgem_bo_destroy(&sna->kgem, tmp);
+ return NULL;
+ }
+
+ kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
+ priv->gpu_bo = tmp;
+ }
+
+ priv->pinned |= PIN_SCANOUT;
+ return priv->gpu_bo;
+}
+
static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
{
struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
@@ -1812,14 +1934,28 @@ static struct kgem_bo *sna_crtc_attach(x
unsigned long tiled_limit;
int tiling;
+force_shadow:
if (!sna_crtc_enable_shadow(sna, sna_crtc)) {
- DBG(("%s: failed to enable crtc shadow\n"));
+ DBG(("%s: failed to enable crtc shadow\n", __FUNCTION__));
return NULL;
}
DBG(("%s: attaching to per-crtc pixmap %dx%d\n",
__FUNCTION__, crtc->mode.HDisplay, crtc->mode.VDisplay));
+ bo = sna_crtc->shadow_bo;
+ if (bo) {
+ if (sna_crtc->shadow_bo_width == crtc->mode.HDisplay &&
+ sna_crtc->shadow_bo_height == crtc->mode.VDisplay) {
+ DBG(("%s: reusing current shadow bo handle=%d\n",
+ __FUNCTION__, bo->handle));
+ goto out_shadow;
+ }
+
+ kgem_bo_destroy(&sna->kgem, bo);
+ sna_crtc->shadow_bo = NULL;
+ }
+
tiling = I915_TILING_X;
if (sna->kgem.gen == 071)
tiled_limit = 16 * 1024 * 8;
@@ -1839,44 +1975,83 @@ static struct kgem_bo *sna_crtc_attach(x
scrn->bitsPerPixel,
tiling, CREATE_SCANOUT);
if (bo == NULL) {
- DBG(("%s: failed to allocate crtc scanout\n"));
+ DBG(("%s: failed to allocate crtc scanout\n", __FUNCTION__));
return NULL;
}
if (!get_fb(sna, bo, crtc->mode.HDisplay, crtc->mode.VDisplay)) {
- DBG(("%s: failed to bind fb for crtc scanout\n"));
+ DBG(("%s: failed to bind fb for crtc scanout\n", __FUNCTION__));
kgem_bo_destroy(&sna->kgem, bo);
return NULL;
}
+ if (__sna_pixmap_get_bo(sna->front) && !crtc->transformPresent) {
+ DrawableRec tmp;
+ BoxRec b;
+
+ b.x1 = crtc->x;
+ b.y1 = crtc->y;
+ b.x2 = crtc->x + crtc->mode.HDisplay;
+ b.y2 = crtc->y + crtc->mode.VDisplay;
+
+ DBG(("%s: copying onto shadow CRTC: (%d, %d)x(%d, %d), handle=%d\n",
+ __FUNCTION__,
+ b.x1, b.y1,
+ b.x2, b.y2,
+ bo->handle));
+
+ tmp.width = crtc->mode.HDisplay;
+ tmp.height = crtc->mode.VDisplay;
+ tmp.depth = sna->front->drawable.depth;
+ tmp.bitsPerPixel = sna->front->drawable.bitsPerPixel;
+
+ (void)sna->render.copy_boxes(sna, GXcopy,
+ &sna->front->drawable, __sna_pixmap_get_bo(sna->front), 0, 0,
+ &tmp, bo, -b.x1, -b.y1,
+ &b, 1, 0);
+ }
+
+ sna_crtc->shadow_bo_width = crtc->mode.HDisplay;
+ sna_crtc->shadow_bo_height = crtc->mode.VDisplay;
+ sna_crtc->shadow_bo = bo;
+out_shadow:
sna_crtc->transform = true;
- return bo;
+ return kgem_bo_reference(bo);
} else {
+ if (sna_crtc->shadow_bo) {
+ kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
+ sna_crtc->shadow_bo = NULL;
+ }
+
if (sna_crtc->slave_pixmap) {
DBG(("%s: attaching to scanout pixmap\n", __FUNCTION__));
- bo = sna_pixmap_pin(sna_crtc->slave_pixmap, PIN_SCANOUT);
+ bo = get_scanout_bo(sna, sna_crtc->slave_pixmap);
if (bo == NULL) {
- DBG(("%s: failed to pin crtc scanout\n"));
- return NULL;
+ DBG(("%s: failed to pin crtc scanout\n", __FUNCTION__));
+ sna_crtc->fallback_shadow = true;
+ goto force_shadow;
}
if (!get_fb(sna, bo,
sna_crtc->slave_pixmap->drawable.width,
sna_crtc->slave_pixmap->drawable.height)) {
- DBG(("%s: failed to bind fb for crtc scanout\n"));
- return NULL;
+ DBG(("%s: failed to bind fb for crtc scanout\n", __FUNCTION__));
+ sna_crtc->fallback_shadow = true;
+ goto force_shadow;
}
} else {
DBG(("%s: attaching to framebuffer\n", __FUNCTION__));
- bo = sna_pixmap_pin(sna->front, PIN_SCANOUT);
+ bo = get_scanout_bo(sna, sna->front);
if (bo == NULL) {
DBG(("%s: failed to pin framebuffer\n", __FUNCTION__));
- return NULL;
+ sna_crtc->fallback_shadow = true;
+ goto force_shadow;
}
if (!get_fb(sna, bo, scrn->virtualX, scrn->virtualY)) {
- DBG(("%s: failed to bind fb for crtc scanout\n"));
- return NULL;
+ DBG(("%s: failed to bind fb for crtc scanout\n", __FUNCTION__));
+ sna_crtc->fallback_shadow = true;
+ goto force_shadow;
}
}
@@ -1885,11 +2060,11 @@ static struct kgem_bo *sna_crtc_attach(x
DBG(("%s: enabling TearFree shadow\n", __FUNCTION__));
if (!sna_crtc_enable_shadow(sna, sna_crtc)) {
- DBG(("%s: failed to enable crtc shadow\n"));
+ DBG(("%s: failed to enable crtc shadow\n", __FUNCTION__));
return NULL;
}
- if (sna->mode.shadow == NULL) {
+ if (sna->mode.shadow == NULL && !wedged(sna)) {
RegionRec region;
struct kgem_bo *shadow;
@@ -1913,15 +2088,17 @@ static struct kgem_bo *sna_crtc_attach(x
CREATE_SCANOUT);
if (shadow == NULL) {
DBG(("%s: failed to allocate TearFree shadow bo\n", __FUNCTION__));
- return NULL;
+ sna_crtc->fallback_shadow = true;
+ goto force_shadow;
}
if (!get_fb(sna, shadow,
region.extents.x2,
region.extents.y2)) {
- DBG(("%s: failed to bind fb for TearFeee shadow\n"));
+ DBG(("%s: failed to bind fb for TearFeee shadow\n", __FUNCTION__));
kgem_bo_destroy(&sna->kgem, shadow);
- return NULL;
+ sna_crtc->fallback_shadow = true;
+ goto force_shadow;
}
sna->mode.shadow = shadow;
@@ -2035,6 +2212,7 @@ sna_crtc_damage(xf86CrtcPtr crtc)
__FUNCTION__, to_sna_crtc(crtc)->id,
region.extents.x1, region.extents.y1,
region.extents.x2, region.extents.y2));
+ to_sna_crtc(crtc)->client_damage = region;
assert(sna->mode.shadow_damage && sna->mode.shadow_active);
damage = DamageRegion(sna->mode.shadow_damage);
@@ -2099,6 +2277,8 @@ __sna_crtc_set_mode(xf86CrtcPtr crtc)
uint32_t saved_offset;
bool saved_transform;
+ DBG(("%s\n", __FUNCTION__));
+
saved_bo = sna_crtc->bo;
saved_transform = sna_crtc->transform;
saved_offset = sna_crtc->offset;
@@ -2112,7 +2292,9 @@ retry: /* Attach per-crtc pixmap or dire
goto error;
}
- kgem_bo_submit(&sna->kgem, bo);
+ /* Prevent recursion when enabling outputs during execbuffer */
+ if (bo->exec && RQ(bo->rq)->bo == NULL)
+ _kgem_submit(&sna->kgem);
sna_crtc->bo = bo;
if (!sna_crtc_apply(crtc)) {
@@ -2143,6 +2325,7 @@ retry: /* Attach per-crtc pixmap or dire
sna_crtc_damage(crtc);
sna->mode.front_active += saved_bo == NULL;
sna->mode.dirty = true;
+ DBG(("%s: front_active=%d\n", __FUNCTION__, sna->mode.front_active));
return TRUE;
@@ -2150,6 +2333,7 @@ error:
sna_crtc->offset = saved_offset;
sna_crtc->transform = saved_transform;
sna_crtc->bo = saved_bo;
+ sna_mode_discover(sna);
return FALSE;
}
@@ -2206,11 +2390,12 @@ sna_crtc_dpms(xf86CrtcPtr crtc, int mode
assert(priv);
priv->dpms_mode = mode;
- if (mode == DPMSModeOn &&
- crtc->enabled &&
- priv->bo == NULL &&
- !__sna_crtc_set_mode(crtc))
- mode = DPMSModeOff;
+ if (mode == DPMSModeOn && crtc->enabled && priv->bo == NULL) {
+ if (__sna_crtc_set_mode(crtc))
+ update_flush_interval(to_sna(crtc->scrn));
+ else
+ mode = DPMSModeOff;
+ }
if (mode != DPMSModeOn)
sna_crtc_disable(crtc);
@@ -2362,8 +2547,8 @@ static int plane_details(struct sna *sna
continue;
}
- DBG(("%s: prop[%d] .id=%d, .name=%s, .flags=%x, .value=%ld\n", __FUNCTION__, i,
- (long)props[i], prop.name, prop.flags, (long)values[i]));
+ DBG(("%s: prop[%d] .id=%ld, .name=%s, .flags=%x, .value=%ld\n", __FUNCTION__, i,
+ (long)props[i], prop.name, (unsigned)prop.flags, (long)values[i]));
if (strcmp(prop.name, "type") == 0) {
type = values[i];
@@ -2437,7 +2622,7 @@ sna_crtc_find_planes(struct sna *sna, st
return;
}
- DBG(("%s: %d planes\n", __FUNCTION__, r.count_planes));
+ DBG(("%s: %d planes\n", __FUNCTION__, (int)r.count_planes));
if (r.count_planes > ARRAY_SIZE(stack_planes)) {
planes = malloc(sizeof(uint32_t)*r.count_planes);
@@ -2556,7 +2741,7 @@ sna_crtc_add(ScrnInfoPtr scrn, int id)
}
sna_crtc->pipe = get_pipe.pipe;
- if (xf86IsEntityShared(scrn->entityList[0]) &&
+ if (is_zaphod(scrn) &&
scrn->confScreen->device->screen != sna_crtc->pipe) {
free(sna_crtc);
return true;
@@ -3009,7 +3194,7 @@ sna_output_dpms(xf86OutputPtr output, in
__FUNCTION__, sna_output->backlight_active_level));
}
sna_output->dpms_mode = dpms;
- sna_output_backlight_set(sna_output, 0);
+ sna_output_backlight_off(sna_output);
}
if (output->crtc &&
@@ -3022,8 +3207,7 @@ sna_output_dpms(xf86OutputPtr output, in
if (sna_output->backlight.iface && dpms == DPMSModeOn) {
DBG(("%s: restoring previous backlight %d\n",
__FUNCTION__, sna_output->backlight_active_level));
- sna_output_backlight_set(sna_output,
- sna_output->backlight_active_level);
+ sna_output_backlight_on(sna_output);
}
sna_output->dpms_mode = dpms;
@@ -3500,7 +3684,7 @@ static int name_from_path(struct sna *sn
char *name)
{
struct drm_mode_get_blob blob;
- char buf[32], *path = buf;
+ char *path;
int id;
id = find_property(sna, sna_output, "PATH");
@@ -3510,20 +3694,19 @@ static int name_from_path(struct sna *sn
VG_CLEAR(blob);
blob.blob_id = sna_output->prop_values[id];
- blob.length = sizeof(buf)-1;
- blob.data = (uintptr_t)path;
- VG(memset(path, 0, blob.length));
+ blob.length = 0;
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
return 0;
- if (blob.length >= sizeof(buf)) {
- path = alloca(blob.length + 1);
+ do {
+ id = blob.length;
+ path = alloca(id + 1);
blob.data = (uintptr_t)path;
- VG(memset(path, 0, blob.length));
- DBG(("%s: reading %d bytes for path blob\n", __FUNCTION__, blob.length));
+ VG(memset(path, 0, id));
+ DBG(("%s: reading %d bytes for path blob\n", __FUNCTION__, id));
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
return 0;
- }
+ } while (id != blob.length);
path[blob.length] = '\0'; /* paranoia */
DBG(("%s: PATH='%s'\n", __FUNCTION__, path));
@@ -3548,7 +3731,8 @@ static int name_from_path(struct sna *sn
for (n = 0; n < sna->mode.num_real_output; n++) {
if (to_sna_output(config->output[n])->id == id)
- return snprintf(name, 32, "%s-%s", config->output[n]->name, c + 1);
+ return snprintf(name, 32, "%s-%s",
+ config->output[n]->name, c + 1);
}
}
@@ -3636,7 +3820,7 @@ sna_output_add(struct sna *sna, unsigned
(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETENCODER, &enc);
}
- if (xf86IsEntityShared(scrn->entityList[0])) {
+ if (is_zaphod(scrn)) {
const char *str;
str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
@@ -3735,7 +3919,7 @@ sna_output_add(struct sna *sna, unsigned
output->name = (char *)(output + 1);
memcpy(output->name, name, len + 1);
- output->use_screen_monitor = config->num_output != 1;
+ output->use_screen_monitor = config->num_output != 0;
xf86OutputUseScreenMonitor(output, !output->use_screen_monitor);
assert(output->options);
@@ -3898,7 +4082,7 @@ static void sort_randr_outputs(struct sn
}
}
-static void disable_unused_crtc(struct sna *sna)
+static bool disable_unused_crtc(struct sna *sna)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
bool update = false;
@@ -3910,7 +4094,6 @@ static void disable_unused_crtc(struct s
if (!crtc->enabled)
continue;
-
for (o = 0; o < sna->mode.num_real_output; o++) {
xf86OutputPtr output = config->output[o];
if (output->crtc == crtc)
@@ -3918,13 +4101,19 @@ static void disable_unused_crtc(struct s
}
if (o == sna->mode.num_real_output) {
+ DBG(("%s: CRTC:%d was enabled with no outputs\n",
+ __FUNCTION__, to_sna_crtc(crtc)->id));
crtc->enabled = false;
update = true;
}
}
- if (update)
+ if (update) {
+ DBG(("%s: disabling unused functions\n", __FUNCTION__));
xf86DisableUnusedFunctions(sna->scrn);
+ }
+
+ return update;
}
void sna_mode_discover(struct sna *sna)
@@ -3952,7 +4141,7 @@ void sna_mode_discover(struct sna *sna)
if (res.count_connectors > 32)
return;
- assert(sna->mode.num_real_crtc == res.count_crtcs);
+ assert(sna->mode.num_real_crtc == res.count_crtcs || is_zaphod(sna->scrn));
assert(sna->mode.max_crtc_width == res.max_width);
assert(sna->mode.max_crtc_height == res.max_height);
assert(sna->mode.num_real_encoder == res.count_encoders);
@@ -4034,7 +4223,7 @@ static void copy_front(struct sna *sna,
if (!old_priv)
return;
- new_priv = sna_pixmap_force_to_gpu(new, MOVE_WRITE);
+ new_priv = sna_pixmap_force_to_gpu(new, MOVE_WRITE | __MOVE_SCANOUT);
if (!new_priv)
return;
@@ -4186,16 +4375,14 @@ sna_mode_resize(ScrnInfoPtr scrn, int wi
xf86CrtcPtr crtc = config->crtc[i];
assert(to_sna_crtc(crtc) != NULL);
- if (!crtc->enabled)
+ if (to_sna_crtc(crtc)->bo == NULL)
continue;
if (!__sna_crtc_set_mode(crtc))
sna_crtc_disable(crtc);
}
- while (sna_mode_has_pending_events(sna))
- sna_mode_wakeup(sna);
-
+ sna_mode_wakeup(sna);
kgem_clean_scanout_cache(&sna->kgem);
return TRUE;
@@ -4574,6 +4761,7 @@ sna_show_cursors(ScrnInfoPtr scrn)
}
}
sigio_unblock(sigio);
+ sna->cursor.active = true;
}
static void
@@ -4638,6 +4826,7 @@ sna_hide_cursors(ScrnInfoPtr scrn)
int sigio, c;
DBG(("%s\n", __FUNCTION__));
+ sna->cursor.active = false;
sigio = sigio_block();
for (c = 0; c < sna->mode.num_real_crtc; c++) {
@@ -4982,9 +5171,11 @@ sna_cursors_init(ScreenPtr screen, struc
static void
sna_cursors_reload(struct sna *sna)
{
- sna_set_cursor_position(sna->scrn,
- sna->cursor.last_x,
- sna->cursor.last_y);
+ DBG(("%s: active?=%d\n", __FUNCTION__, sna->cursor.active));
+ if (sna->cursor.active)
+ sna_set_cursor_position(sna->scrn,
+ sna->cursor.last_x,
+ sna->cursor.last_y);
}
static void
@@ -5013,6 +5204,8 @@ sna_crtc_flip(struct sna *sna, struct sn
DBG(("%s CRTC:%d [pipe=%d], handle=%d\n", __FUNCTION__, crtc->id, crtc->pipe, bo->handle));
assert(sna->mode.num_real_output < ARRAY_SIZE(output_ids));
+ assert(crtc->bo);
+ assert(crtc->kmode.clock);
for (i = 0; i < sna->mode.num_real_output; i++) {
xf86OutputPtr output = config->output[i];
@@ -5027,12 +5220,13 @@ sna_crtc_flip(struct sna *sna, struct sn
(uint32_t)output->possible_clones));
assert(output->possible_crtcs & (1 << crtc->pipe) ||
- xf86IsEntityShared(sna->scrn->entityList[0]));
+ is_zaphod(sna->scrn));
output_ids[output_count] = to_connector_id(output);
if (++output_count == ARRAY_SIZE(output_ids))
return false;
}
+ assert(output_count);
VG_CLEAR(arg);
arg.crtc_id = crtc->id;
@@ -5123,6 +5317,11 @@ fixup_flip:
crtc->bo->active_scanout--;
kgem_bo_destroy(&sna->kgem, crtc->bo);
+ if (crtc->shadow_bo) {
+ kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
+ crtc->shadow_bo = NULL;
+ }
+
crtc->bo = kgem_bo_reference(bo);
crtc->bo->active_scanout++;
@@ -5198,6 +5397,7 @@ retry_flip:
crtc->flip_bo = kgem_bo_reference(bo);
crtc->flip_bo->active_scanout++;
crtc->flip_serial = crtc->mode_serial;
+ crtc->flip_pending = true;
sna->mode.flip_active++;
}
@@ -5612,11 +5812,19 @@ sna_crtc_config_notify(ScreenPtr screen)
if (!sna->mode.dirty)
return;
- probe_capabilities(sna);
- update_flush_interval(sna);
+ if (disable_unused_crtc(sna)) {
+ /* This will have recursed, so simply bail at this point */
+ assert(sna->mode.dirty == false);
+#ifdef RANDR_12_INTERFACE
+ xf86RandR12TellChanged(screen);
+#endif
+ return;
+ }
+ update_flush_interval(sna);
sna_cursors_reload(sna);
+ probe_capabilities(sna);
sna_present_update(sna);
sna->mode.dirty = false;
@@ -5744,7 +5952,7 @@ sna_mode_set_primary(struct sna *sna)
rrScrPrivPtr rr = rrGetScrPriv(xf86ScrnToScreen(sna->scrn));
int i;
- if (rr->primaryOutput)
+ if (rr == NULL || rr->primaryOutput)
return;
for (i = 0; i < sna->mode.num_real_output; i++) {
@@ -5762,11 +5970,68 @@ sna_mode_set_primary(struct sna *sna)
#endif
}
+bool
+sna_mode_disable(struct sna *sna)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+ int i;
+
+ if (sna->flags & SNA_IS_HOSTED)
+ return false;
+
+ if (!sna->scrn->vtSema)
+ return false;
+
+ /* XXX we will cause previously hidden cursors to be reshown, but
+ * this should be a rare fixup case for severe fragmentation.
+ */
+ sna_hide_cursors(sna->scrn);
+ for (i = 0; i < sna->mode.num_real_crtc; i++)
+ sna_crtc_disable(config->crtc[i]);
+ assert(sna->mode.front_active == 0);
+
+ sna_mode_wakeup(sna);
+ kgem_clean_scanout_cache(&sna->kgem);
+ return true;
+}
+
+void
+sna_mode_enable(struct sna *sna)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+ int i;
+
+ DBG(("%s\n", __FUNCTION__));
+
+ if (sna->flags & SNA_IS_HOSTED)
+ return;
+
+ if (!sna->scrn->vtSema)
+ return;
+
+ for (i = 0; i < sna->mode.num_real_crtc; i++) {
+ xf86CrtcPtr crtc = config->crtc[i];
+
+ DBG(("%s: crtc[%d].enabled?=%d\n", __FUNCTION__, i, crtc->enabled));
+ assert(to_sna_crtc(crtc) != NULL);
+ if (!crtc->enabled)
+ continue;
+
+ if (crtc->mode.Clock == 0)
+ continue;
+
+ __sna_crtc_set_mode(crtc);
+ }
+
+ update_flush_interval(sna);
+ sna_show_cursors(sna->scrn);
+ sna->mode.dirty = false;
+}
+
void
sna_mode_close(struct sna *sna)
{
- while (sna_mode_has_pending_events(sna))
- sna_mode_wakeup(sna);
+ sna_mode_wakeup(sna);
if (sna->flags & SNA_IS_HOSTED)
return;
@@ -5777,6 +6042,7 @@ sna_mode_close(struct sna *sna)
sna_cursors_fini(sna);
sna_backlight_close(sna);
+ sna->mode.dirty = false;
}
void
@@ -6053,7 +6319,7 @@ static bool sna_emit_wait_for_scanline_g
event = 1 << (3*full_height + pipe*8);
b = kgem_get_batch(&sna->kgem);
- sna->kgem.nbatch += 10;
+ sna->kgem.nbatch += 16;
b[0] = MI_LOAD_REGISTER_IMM | 1;
b[1] = 0x44050; /* DERRMR */
@@ -6061,10 +6327,16 @@ static bool sna_emit_wait_for_scanline_g
b[3] = MI_LOAD_REGISTER_IMM | 1;
b[4] = 0x4f100; /* magic */
b[5] = (1 << 31) | (1 << 30) | pipe << 29 | (y1 << 16) | y2;
- b[6] = MI_WAIT_FOR_EVENT | event;
- b[7] = MI_LOAD_REGISTER_IMM | 1;
- b[8] = 0x44050; /* DERRMR */
- b[9] = ~0;
+ b[6] = MI_LOAD_REGISTER_IMM | 1;
+ b[7] = 0x2050; /* PSMI_CTL(rcs) */
+ b[8] = 1 << 16 | 1;
+ b[9] = MI_WAIT_FOR_EVENT | event;
+ b[10] = MI_LOAD_REGISTER_IMM | 1;
+ b[11] = 0x2050; /* PSMI_CTL(rcs) */
+ b[12] = 1 << 16;
+ b[13] = MI_LOAD_REGISTER_IMM | 1;
+ b[14] = 0x44050; /* DERRMR */
+ b[15] = ~0;
sna->kgem.batch_flags |= I915_EXEC_SECURE;
return true;
@@ -6283,6 +6555,7 @@ sna_crtc_hide_planes(struct sna *sna, st
s.plane_id = crtc->sprite.id;
(void)drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s);
+ __sna_crtc_disable(sna, crtc);
return true;
}
@@ -6329,8 +6602,7 @@ void sna_mode_reset(struct sna *sna)
}
/* drain the event queue */
- while (sna_mode_has_pending_events(sna))
- sna_mode_wakeup(sna);
+ sna_mode_wakeup(sna);
}
static void transformed_box(BoxRec *box, xf86CrtcPtr crtc)
@@ -6356,10 +6628,17 @@ inline static DrawablePtr crtc_source(xf
{
struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
if (sna_crtc->slave_pixmap) {
+ DBG(("%s: using slave pixmap=%ld, offset (%d, %d)\n",
+ __FUNCTION__,
+ sna_crtc->slave_pixmap->drawable.serialNumber,
+ -crtc->x, -crtc->y));
*sx = -crtc->x;
*sy = -crtc->y;
return &sna_crtc->slave_pixmap->drawable;
} else {
+ DBG(("%s: using Screen pixmap=%ld\n",
+ __FUNCTION__,
+ to_sna(crtc->scrn)->front->drawable.serialNumber));
*sx = *sy = 0;
return &to_sna(crtc->scrn)->front->drawable;
}
@@ -6378,7 +6657,7 @@ sna_crtc_redisplay__fallback(xf86CrtcPtr
int depth, error;
void *ptr;
- DBG(("%s: compositing transformed damage boxes\n", __FUNCTION__));
+ DBG(("%s: compositing transformed damage boxes, target handle=%d\n", __FUNCTION__, bo->handle));
error = sna_render_format_for_depth(draw->depth);
depth = PIXMAN_FORMAT_DEPTH(error);
@@ -6389,6 +6668,10 @@ sna_crtc_redisplay__fallback(xf86CrtcPtr
return;
}
+ DBG(("%s: dst format=%08x, depth=%d, bpp=%d, pitch=%d, size=%dx%d\n",
+ __FUNCTION__, format->format, depth, draw->bitsPerPixel,
+ bo->pitch, crtc->mode.HDisplay, crtc->mode.VDisplay));
+
ptr = kgem_bo_map__gtt(&sna->kgem, bo);
if (ptr == NULL)
return;
@@ -6412,7 +6695,7 @@ sna_crtc_redisplay__fallback(xf86CrtcPtr
if (error)
goto free_src;
- if (crtc->filter)
+ if (crtc->filter && crtc->transform_in_use)
SetPicturePictFilter(src, crtc->filter,
crtc->params, crtc->nparams);
@@ -6478,6 +6761,10 @@ sna_crtc_redisplay__composite(xf86CrtcPt
return;
}
+ DBG(("%s: dst format=%08x, depth=%d, bpp=%d, pitch=%d, size=%dx%d\n",
+ __FUNCTION__, format->format, depth, draw->bitsPerPixel,
+ bo->pitch, crtc->mode.HDisplay, crtc->mode.VDisplay));
+
pixmap = sna_pixmap_create_unattached(screen, 0, 0, depth);
if (pixmap == NullPixmap)
return;
@@ -6502,7 +6789,7 @@ sna_crtc_redisplay__composite(xf86CrtcPt
if (error)
goto free_src;
- if (crtc->filter)
+ if (crtc->filter && crtc->transform_in_use)
SetPicturePictFilter(src, crtc->filter,
crtc->params, crtc->nparams);
@@ -6590,6 +6877,8 @@ sna_crtc_redisplay(xf86CrtcPtr crtc, Reg
}
if (crtc->filter == NULL &&
+ priv->gpu_bo &&
+ priv->cpu_damage == NULL &&
sna_transform_is_integer_translation(&crtc->crtc_to_framebuffer,
&tx, &ty)) {
DrawableRec tmp;
@@ -6614,7 +6903,11 @@ sna_crtc_redisplay(xf86CrtcPtr crtc, Reg
sna_crtc_redisplay__fallback(crtc, region, bo);
}
-#define shadow_flip_handler (sna_flip_handler_t)sna_mode_redisplay
+static void shadow_flip_handler(struct drm_event_vblank *e,
+ void *data)
+{
+ sna_mode_redisplay(data);
+}
void sna_shadow_set_crtc(struct sna *sna,
xf86CrtcPtr crtc,
@@ -6630,11 +6923,11 @@ void sna_shadow_set_crtc(struct sna *sna
assert(sna_crtc);
assert(!sna_crtc->transform);
- if (sna_crtc->shadow_bo != bo) {
- if (sna_crtc->shadow_bo)
- kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
+ if (sna_crtc->client_bo != bo) {
+ if (sna_crtc->client_bo)
+ kgem_bo_destroy(&sna->kgem, sna_crtc->client_bo);
- sna_crtc->shadow_bo = kgem_bo_reference(bo);
+ sna_crtc->client_bo = kgem_bo_reference(bo);
sna_crtc_damage(crtc);
}
@@ -6647,19 +6940,50 @@ void sna_shadow_set_crtc(struct sna *sna
priv->move_to_gpu_data = sna;
}
+void sna_shadow_steal_crtcs(struct sna *sna, struct list *list)
+{
+ list_init(list);
+ while (!list_is_empty(&sna->mode.shadow_crtc)) {
+ RegionRec sub, *damage;
+ struct sna_crtc *crtc =
+ list_first_entry(&sna->mode.shadow_crtc,
+ struct sna_crtc,
+ shadow_link);
+
+ damage = DamageRegion(sna->mode.shadow_damage);
+ sub.extents = crtc->base->bounds;
+ sub.data = NULL;
+ RegionSubtract(damage, damage, &sub);
+
+ list_move(&crtc->shadow_link, list);
+ }
+}
+
+void sna_shadow_unsteal_crtcs(struct sna *sna, struct list *list)
+{
+ while (!list_is_empty(list)) {
+ struct sna_crtc *crtc =
+ list_first_entry(list,
+ struct sna_crtc,
+ shadow_link);
+ assert(crtc->client_bo);
+ sna_shadow_set_crtc(sna, crtc->base, crtc->client_bo);
+ }
+}
+
void sna_shadow_unset_crtc(struct sna *sna,
- xf86CrtcPtr crtc)
+ xf86CrtcPtr crtc)
{
struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
DBG(("%s: clearin shadow override for CRTC:%d\n",
__FUNCTION__, sna_crtc->id));
- if (sna_crtc->shadow_bo == NULL)
+ if (sna_crtc->client_bo == NULL)
return;
- kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
- sna_crtc->shadow_bo = NULL;
+ kgem_bo_destroy(&sna->kgem, sna_crtc->client_bo);
+ sna_crtc->client_bo = NULL;
list_del(&sna_crtc->shadow_link);
sna->mode.shadow_dirty = true;
@@ -6675,13 +6999,17 @@ void sna_mode_redisplay(struct sna *sna)
if (!sna->mode.shadow_damage)
return;
- DBG(("%s: posting shadow damage? %d (flips pending? %d)\n",
+ DBG(("%s: posting shadow damage? %d (flips pending? %d, mode reconfiguration pending? %d)\n",
__FUNCTION__,
!RegionNil(DamageRegion(sna->mode.shadow_damage)),
- sna->mode.flip_active));
+ sna->mode.flip_active,
+ sna->mode.dirty));
assert((sna->flags & SNA_IS_HOSTED) == 0);
assert(sna->mode.shadow_active);
+ if (sna->mode.dirty)
+ return;
+
region = DamageRegion(sna->mode.shadow_damage);
if (RegionNil(region))
return;
@@ -6697,8 +7025,8 @@ void sna_mode_redisplay(struct sna *sna)
damage = sna->mode.shadow_damage;
sna->mode.shadow_damage = NULL;
- while (sna->mode.flip_active && sna_mode_has_pending_events(sna))
- sna_mode_wakeup(sna);
+ while (sna->mode.flip_active && sna_mode_wakeup(sna))
+ ;
sna->mode.shadow_damage = damage;
}
@@ -6726,8 +7054,92 @@ void sna_mode_redisplay(struct sna *sna)
damage.extents = crtc->bounds;
damage.data = NULL;
RegionIntersect(&damage, &damage, region);
- if (RegionNotEmpty(&damage))
- sna_crtc_redisplay__fallback(crtc, &damage, sna_crtc->bo);
+ if (!box_empty(&damage.extents)) {
+ struct kgem_bo *bo = NULL;
+
+ DBG(("%s: fallback intersects pipe=%d [(%d, %d), (%d, %d)]\n",
+ __FUNCTION__, sna_crtc->pipe,
+ damage.extents.x1, damage.extents.y1,
+ damage.extents.x2, damage.extents.y2));
+
+ if (sna->flags & SNA_TEAR_FREE) {
+ RegionRec new_damage;
+
+ RegionNull(&new_damage);
+ RegionCopy(&new_damage, &damage);
+
+ bo = sna_crtc->client_bo;
+ if (bo == NULL) {
+ damage.extents = crtc->bounds;
+ damage.data = NULL;
+ bo = kgem_create_2d(&sna->kgem,
+ crtc->mode.HDisplay,
+ crtc->mode.VDisplay,
+ crtc->scrn->bitsPerPixel,
+ sna_crtc->bo->tiling,
+ CREATE_SCANOUT);
+ } else
+ RegionUnion(&damage, &damage, &sna_crtc->client_damage);
+
+ DBG(("%s: TearFree fallback, shadow handle=%d, crtc handle=%d\n", __FUNCTION__, bo->handle, sna_crtc->bo->handle));
+
+ sna_crtc->client_damage = new_damage;
+ }
+
+ if (bo == NULL)
+ bo = sna_crtc->bo;
+ sna_crtc_redisplay__fallback(crtc, &damage, bo);
+
+ if (bo != sna_crtc->bo) {
+ struct drm_mode_crtc_page_flip arg;
+
+ arg.crtc_id = sna_crtc->id;
+ arg.fb_id = get_fb(sna, bo,
+ crtc->mode.HDisplay,
+ crtc->mode.VDisplay);
+
+ arg.user_data = (uintptr_t)sna_crtc;
+ arg.flags = DRM_MODE_PAGE_FLIP_EVENT;
+ arg.reserved = 0;
+
+ if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
+ if (sna_crtc_flip(sna, sna_crtc, bo, 0, 0)) {
+ assert(sna_crtc->bo->active_scanout);
+ assert(sna_crtc->bo->refcnt >= sna_crtc->bo->active_scanout);
+ sna_crtc->bo->active_scanout--;
+ kgem_bo_destroy(&sna->kgem, sna_crtc->bo);
+
+ sna_crtc->bo = bo;
+ sna_crtc->bo->active_scanout++;
+ sna_crtc->client_bo = NULL;
+ } else {
+ DBG(("%s: flip [fb=%d] on crtc %d [%d, pipe=%d] failed - %d\n",
+ __FUNCTION__, arg.fb_id, i, sna_crtc->id, sna_crtc->pipe, errno));
+ xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
+ "Page flipping failed, disabling TearFree\n");
+ sna->flags &= ~SNA_TEAR_FREE;
+
+ damage.extents = crtc->bounds;
+ damage.data = NULL;
+ sna_crtc_redisplay__fallback(crtc, &damage, sna_crtc->bo);
+
+ kgem_bo_destroy(&sna->kgem, bo);
+ sna_crtc->client_bo = NULL;
+ }
+ } else {
+ sna->mode.flip_active++;
+
+ assert(sna_crtc->flip_bo == NULL);
+ sna_crtc->flip_handler = shadow_flip_handler;
+ sna_crtc->flip_data = sna;
+ sna_crtc->flip_bo = bo;
+ sna_crtc->flip_bo->active_scanout++;
+ sna_crtc->flip_serial = sna_crtc->mode_serial;
+
+ sna_crtc->client_bo = kgem_bo_reference(sna_crtc->bo);
+ }
+ }
+ }
RegionUninit(&damage);
if (sna_crtc->slave_damage)
@@ -6782,7 +7194,13 @@ void sna_mode_redisplay(struct sna *sna)
damage.data = NULL;
RegionIntersect(&damage, &damage, region);
- if (RegionNotEmpty(&damage)) {
+ DBG(("%s: crtc[%d] damage? %d[%d]: %dx[(%d, %d), (%d, %d)]\n",
+ __FUNCTION__, i,
+ !box_empty(&damage.extents), RegionNotEmpty(&damage),
+ region_num_rects(&damage),
+ damage.extents.x1, damage.extents.y1,
+ damage.extents.x2, damage.extents.y2));
+ if (!box_empty(&damage.extents)) {
if (sna->flags & SNA_TEAR_FREE) {
struct drm_mode_crtc_page_flip arg;
struct kgem_bo *bo;
@@ -6791,7 +7209,7 @@ void sna_mode_redisplay(struct sna *sna)
damage.extents = crtc->bounds;
damage.data = NULL;
- bo = sna_crtc->shadow_bo;
+ bo = sna_crtc->client_bo;
if (bo == NULL)
bo = kgem_create_2d(&sna->kgem,
crtc->mode.HDisplay,
@@ -6817,42 +7235,59 @@ void sna_mode_redisplay(struct sna *sna)
arg.reserved = 0;
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
- BoxRec box;
- DrawableRec tmp;
+ if (sna_crtc_flip(sna, sna_crtc, bo, 0, 0)) {
+ assert(sna_crtc->bo->active_scanout);
+ assert(sna_crtc->bo->refcnt >= sna_crtc->bo->active_scanout);
+ sna_crtc->bo->active_scanout--;
+ kgem_bo_destroy(&sna->kgem, sna_crtc->bo);
+
+ sna_crtc->bo = kgem_bo_reference(bo);
+ sna_crtc->bo->active_scanout++;
+ sna_crtc->client_bo = kgem_bo_reference(bo);
+ } else {
+ BoxRec box;
+ DrawableRec tmp;
+
+ DBG(("%s: flip [fb=%d] on crtc %d [%d, pipe=%d] failed - %d\n",
+ __FUNCTION__, arg.fb_id, i, sna_crtc->id, sna_crtc->pipe, errno));
+ xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
+ "Page flipping failed, disabling TearFree\n");
+ sna->flags &= ~SNA_TEAR_FREE;
- DBG(("%s: flip [fb=%d] on crtc %d [%d, pipe=%d] failed - %d\n",
- __FUNCTION__, arg.fb_id, i, sna_crtc->id, sna_crtc->pipe, errno));
disable1:
- box.x1 = 0;
- box.y1 = 0;
- tmp.width = box.x2 = crtc->mode.HDisplay;
- tmp.height = box.y2 = crtc->mode.VDisplay;
- tmp.depth = sna->front->drawable.depth;
- tmp.bitsPerPixel = sna->front->drawable.bitsPerPixel;
-
- if (!sna->render.copy_boxes(sna, GXcopy,
- &sna->front->drawable, bo, 0, 0,
- &tmp, sna_crtc->bo, 0, 0,
- &box, 1, COPY_LAST)) {
- xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
- "%s: page flipping failed, disabling CRTC:%d (pipe=%d)\n",
- __FUNCTION__, sna_crtc->id, sna_crtc->pipe);
- sna_crtc_disable(crtc);
- }
+ box.x1 = 0;
+ box.y1 = 0;
+ tmp.width = box.x2 = crtc->mode.HDisplay;
+ tmp.height = box.y2 = crtc->mode.VDisplay;
+ tmp.depth = sna->front->drawable.depth;
+ tmp.bitsPerPixel = sna->front->drawable.bitsPerPixel;
+
+ if (!sna->render.copy_boxes(sna, GXcopy,
+ &sna->front->drawable, bo, 0, 0,
+ &tmp, sna_crtc->bo, 0, 0,
+ &box, 1, COPY_LAST)) {
+ xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+ "%s: page flipping failed, disabling CRTC:%d (pipe=%d)\n",
+ __FUNCTION__, sna_crtc->id, sna_crtc->pipe);
+ sna_crtc_disable(crtc);
+ }
- kgem_bo_destroy(&sna->kgem, bo);
- sna_crtc->shadow_bo = NULL;
+ kgem_bo_destroy(&sna->kgem, bo);
+ sna_crtc->client_bo = NULL;
+ }
continue;
}
sna->mode.flip_active++;
assert(sna_crtc->flip_bo == NULL);
sna_crtc->flip_handler = shadow_flip_handler;
+ sna_crtc->flip_data = sna;
sna_crtc->flip_bo = bo;
sna_crtc->flip_bo->active_scanout++;
sna_crtc->flip_serial = sna_crtc->mode_serial;
+ sna_crtc->flip_pending = true;
- sna_crtc->shadow_bo = kgem_bo_reference(sna_crtc->bo);
+ sna_crtc->client_bo = kgem_bo_reference(sna_crtc->bo);
} else {
sna_crtc_redisplay(crtc, &damage, sna_crtc->bo);
kgem_scanout_flush(&sna->kgem, sna_crtc->bo);
@@ -6870,7 +7305,7 @@ disable1:
struct drm_mode_crtc_page_flip arg;
uint32_t fb = 0;
- DBG(("%s: flipping tear-free outputs, current scanout handle=%d [active?=%d], new handle=%d [active=%d]\n",
+ DBG(("%s: flipping TearFree outputs, current scanout handle=%d [active?=%d], new handle=%d [active=%d]\n",
__FUNCTION__, old->handle, old->active_scanout, new->handle, new->active_scanout));
assert(new != old);
@@ -6899,14 +7334,14 @@ disable1:
arg.crtc_id = crtc->id;
arg.user_data = (uintptr_t)crtc;
- if (crtc->shadow_bo) {
+ if (crtc->client_bo) {
DBG(("%s: apply shadow override bo for CRTC:%d on pipe=%d, handle=%d\n",
- __FUNCTION__, crtc->id, crtc->pipe, crtc->shadow_bo->handle));
- arg.fb_id = get_fb(sna, crtc->shadow_bo,
+ __FUNCTION__, crtc->id, crtc->pipe, crtc->client_bo->handle));
+ arg.fb_id = get_fb(sna, crtc->client_bo,
crtc->base->mode.HDisplay,
crtc->base->mode.VDisplay);
assert(arg.fb_id != fb);
- flip_bo = crtc->shadow_bo;
+ flip_bo = crtc->client_bo;
x = y = 0;
} else {
if (fb == 0)
@@ -6942,7 +7377,7 @@ fixup_shadow:
continue;
if (flip_bo->pitch != crtc->bo->pitch || (y << 16 | x) != crtc->offset) {
- DBG(("%s: changing pitch (%d == %d) or offset (%x == %x)\n",
+ DBG(("%s: changing pitch (new %d =?= old %d) or offset (new %x =?= old %x)\n",
__FUNCTION__,
flip_bo->pitch, crtc->bo->pitch,
y << 16 | x, crtc->offset));
@@ -6954,9 +7389,18 @@ fixup_flip:
crtc->bo->active_scanout--;
kgem_bo_destroy(&sna->kgem, crtc->bo);
+ if (crtc->shadow_bo) {
+ kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
+ crtc->shadow_bo = NULL;
+ }
+
crtc->bo = kgem_bo_reference(flip_bo);
crtc->bo->active_scanout++;
} else {
+ xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
+ "Failed to prepare CRTC for page flipping, disabling TearFree\n");
+ sna->flags &= ~SNA_TEAR_FREE;
+
if (sna->mode.flip_active == 0) {
DBG(("%s: abandoning flip attempt\n", __FUNCTION__));
goto fixup_shadow;
@@ -6979,9 +7423,11 @@ fixup_flip:
assert(crtc->flip_bo == NULL);
crtc->flip_handler = shadow_flip_handler;
+ crtc->flip_data = sna;
crtc->flip_bo = kgem_bo_reference(flip_bo);
crtc->flip_bo->active_scanout++;
crtc->flip_serial = crtc->mode_serial;
+ crtc->flip_pending = true;
{
struct drm_i915_gem_busy busy = { flip_bo->handle };
@@ -7014,17 +7460,32 @@ fixup_flip:
RegionEmpty(region);
}
-void sna_mode_wakeup(struct sna *sna)
+int sna_mode_wakeup(struct sna *sna)
{
char buffer[1024];
int len, i;
+ int ret = 0;
+
+again:
+ /* In order to workaround a kernel bug in not honouring O_NONBLOCK,
+ * check that the fd is readable before attempting to read the next
+ * event from drm.
+ */
+ if (!event_pending(sna->kgem.fd))
+ return ret;
/* The DRM read semantics guarantees that we always get only
* complete events.
*/
len = read(sna->kgem.fd, buffer, sizeof (buffer));
if (len < (int)sizeof(struct drm_event))
- return;
+ return ret;
+
+ /* Note that we cannot rely on the passed in struct sna matching
+ * the struct sna used for the vblank event (in case it was submitted
+ * by a different ZaphodHead). When processing the event, we must
+ * ensure that we only use the pointer passed along with the event.
+ */
DBG(("%s: len=%d\n", __FUNCTION__, len));
@@ -7034,18 +7495,22 @@ void sna_mode_wakeup(struct sna *sna)
switch (e->type) {
case DRM_EVENT_VBLANK:
if (((uintptr_t)((struct drm_event_vblank *)e)->user_data) & 2)
- sna_present_vblank_handler(sna, (struct drm_event_vblank *)e);
+ sna_present_vblank_handler((struct drm_event_vblank *)e);
else
- sna_dri2_vblank_handler(sna, (struct drm_event_vblank *)e);
+ sna_dri2_vblank_handler((struct drm_event_vblank *)e);
break;
case DRM_EVENT_FLIP_COMPLETE:
{
struct drm_event_vblank *vbl = (struct drm_event_vblank *)e;
struct sna_crtc *crtc = (void *)(uintptr_t)vbl->user_data;
+ /* Beware Zaphod! */
+ sna = to_sna(crtc->base->scrn);
+
crtc->swap.tv_sec = vbl->tv_sec;
crtc->swap.tv_usec = vbl->tv_usec;
crtc->swap.msc = msc64(crtc, vbl->sequence);
+ crtc->flip_pending = false;
assert(crtc->flip_bo);
assert(crtc->flip_bo->active_scanout);
@@ -7059,6 +7524,11 @@ void sna_mode_wakeup(struct sna *sna)
crtc->bo->active_scanout--;
kgem_bo_destroy(&sna->kgem, crtc->bo);
+ if (crtc->shadow_bo) {
+ kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
+ crtc->shadow_bo = NULL;
+ }
+
crtc->bo = crtc->flip_bo;
crtc->flip_bo = NULL;
} else {
@@ -7070,12 +7540,15 @@ void sna_mode_wakeup(struct sna *sna)
DBG(("%s: flip complete, pending? %d\n", __FUNCTION__, sna->mode.flip_active));
assert(sna->mode.flip_active);
if (--sna->mode.flip_active == 0)
- crtc->flip_handler(sna, vbl, crtc->flip_data);
+ crtc->flip_handler(vbl, crtc->flip_data);
}
break;
default:
break;
}
i += e->length;
+ ret++;
}
+
+ goto again;
}
Index: xsrc/external/mit/xf86-video-intel/dist/src/uxa/intel.h
diff -u xsrc/external/mit/xf86-video-intel/dist/src/uxa/intel.h:1.2 xsrc/external/mit/xf86-video-intel/dist/src/uxa/intel.h:1.3
--- xsrc/external/mit/xf86-video-intel/dist/src/uxa/intel.h:1.2 Wed Nov 5 17:58:59 2014
+++ xsrc/external/mit/xf86-video-intel/dist/src/uxa/intel.h Fri Jan 16 21:32:11 2015
@@ -54,7 +54,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
#include "xorg-server.h"
#include "xf86_OSproc.h"
#include "compiler.h"
-#include "xf86Pci.h"
#include "xf86Cursor.h"
#include "xf86xv.h"
#include "xf86Crtc.h"
@@ -93,64 +92,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
#define MAX_PIPES 4 /* consider making all users dynamic */
-struct intel_pixmap {
- dri_bo *bo;
-
- struct list batch;
-
- uint16_t stride;
- uint8_t tiling;
- int8_t busy :2;
- uint8_t dirty :1;
- uint8_t offscreen :1;
- uint8_t pinned :5;
-#define PIN_SCANOUT 0x1
-#define PIN_DRI2 0x2
-#define PIN_DRI3 0x4
-#define PIN_PRIME 0x8
-#define PIN_GLAMOR 0x10
-};
-
-#if HAS_DEVPRIVATEKEYREC
-extern DevPrivateKeyRec uxa_pixmap_index;
-#else
-extern int uxa_pixmap_index;
-#endif
-
-static inline struct intel_pixmap *intel_get_pixmap_private(PixmapPtr pixmap)
-{
-#if HAS_DEVPRIVATEKEYREC
- return dixGetPrivate(&pixmap->devPrivates, &uxa_pixmap_index);
-#else
- return dixLookupPrivate(&pixmap->devPrivates, &uxa_pixmap_index);
-#endif
-}
-
-static inline Bool intel_pixmap_is_busy(struct intel_pixmap *priv)
-{
- if (priv->busy == -1)
- priv->busy = drm_intel_bo_busy(priv->bo);
- return priv->busy;
-}
-
-static inline void intel_set_pixmap_private(PixmapPtr pixmap, struct intel_pixmap *intel)
-{
- dixSetPrivate(&pixmap->devPrivates, &uxa_pixmap_index, intel);
-}
-
-static inline Bool intel_pixmap_is_dirty(PixmapPtr pixmap)
-{
- return pixmap && intel_get_pixmap_private(pixmap)->dirty;
-}
-
-static inline Bool intel_pixmap_tiled(PixmapPtr pixmap)
-{
- return intel_get_pixmap_private(pixmap)->tiling != I915_TILING_NONE;
-}
-
-dri_bo *intel_get_pixmap_bo(PixmapPtr pixmap);
-void intel_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo);
-
#include "common.h"
#define PITCH_NONE 0
@@ -171,6 +112,7 @@ enum dri_type {
typedef struct intel_screen_private {
ScrnInfoPtr scrn;
+ struct intel_device *dev;
int cpp;
#define RENDER_BATCH I915_EXEC_RENDER
@@ -179,12 +121,12 @@ typedef struct intel_screen_private {
void *modes;
drm_intel_bo *front_buffer, *back_buffer;
- PixmapPtr back_pixmap;
unsigned int back_name;
long front_pitch, front_tiling;
dri_bufmgr *bufmgr;
+#if USE_UXA
uint32_t batch_ptr[4096];
/** Byte offset in batch_ptr for the next dword to be emitted. */
unsigned int batch_used;
@@ -200,6 +142,7 @@ typedef struct intel_screen_private {
struct list batch_pixmaps;
drm_intel_bo *wa_scratch_bo;
OsTimerPtr cache_expire;
+#endif
/* For Xvideo */
Bool use_overlay;
@@ -223,7 +166,6 @@ typedef struct intel_screen_private {
int Chipset;
EntityInfoPtr pEnt;
- struct pci_device *PciInfo;
const struct intel_device_info *info;
unsigned int BR[20];
@@ -236,8 +178,10 @@ typedef struct intel_screen_private {
void (*batch_flush) (struct intel_screen_private *intel);
void (*batch_commit_notify) (struct intel_screen_private *intel);
+#if USE_UXA
struct _UxaDriver *uxa_driver;
int uxa_flags;
+#endif
Bool need_sync;
int accel_pixmap_offset_alignment;
int accel_max_x;
@@ -270,6 +214,7 @@ typedef struct intel_screen_private {
drm_intel_bo *gen6_depth_stencil_bo;
} video;
+#if USE_UXA
/* Render accel state */
float scale_units[2][2];
/** Transform pointers for src/mask, or NULL if identity */
@@ -327,6 +272,7 @@ typedef struct intel_screen_private {
/* 965 render acceleration state */
struct gen4_render_state *gen4_render_state;
+#endif
/* DRI enabled this generation. */
enum dri_type dri2, dri3;
@@ -378,14 +324,14 @@ typedef struct intel_screen_private {
#define IS_HSW(intel) (INTEL_INFO(intel)->gen == 075)
/* Some chips have specific errata (or limits) that we need to workaround. */
-#define IS_I830(intel) ((intel)->PciInfo->device_id == PCI_CHIP_I830_M)
-#define IS_845G(intel) ((intel)->PciInfo->device_id == PCI_CHIP_845_G)
-#define IS_I865G(intel) ((intel)->PciInfo->device_id == PCI_CHIP_I865_G)
+#define IS_I830(intel) (intel_get_device_id((intel)->dev) == PCI_CHIP_I830_M)
+#define IS_845G(intel) (intel_get_device_id((intel)->dev) == PCI_CHIP_845_G)
+#define IS_I865G(intel) (intel_get_device_id((intel)->dev) == PCI_CHIP_I865_G)
-#define IS_I915G(pI810) ((intel)->PciInfo->device_id == PCI_CHIP_I915_G || (intel)->PciInfo->device_id == PCI_CHIP_E7221_G)
-#define IS_I915GM(pI810) ((intel)->PciInfo->device_id == PCI_CHIP_I915_GM)
+#define IS_I915G(pI810) (intel_get_device_id((intel)->dev) == PCI_CHIP_I915_G || intel_get_device_id((intel)->dev) == PCI_CHIP_E7221_G)
+#define IS_I915GM(pI810) (intel_get_device_id((intel)->dev) == PCI_CHIP_I915_GM)
-#define IS_965_Q(pI810) ((intel)->PciInfo->device_id == PCI_CHIP_I965_Q)
+#define IS_965_Q(pI810) (intel_get_device_id((intel)->dev) == PCI_CHIP_I965_Q)
/* supports Y tiled surfaces (pre-965 Mesa isn't ready yet) */
#define SUPPORTS_YTILING(pI810) (INTEL_INFO(intel)->gen >= 040)
@@ -501,22 +447,10 @@ intel_get_screen_private(ScrnInfoPtr scr
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
-static inline unsigned long intel_pixmap_pitch(PixmapPtr pixmap)
-{
- return (unsigned long)pixmap->devKind;
-}
-
-/* Batchbuffer support macros and functions */
-#include "intel_batchbuffer.h"
-
-/* I830 specific functions */
-extern void IntelEmitInvarientState(ScrnInfoPtr scrn);
-extern void I830EmitInvarientState(ScrnInfoPtr scrn);
-extern void I915EmitInvarientState(ScrnInfoPtr scrn);
-
-extern void I830EmitFlush(ScrnInfoPtr scrn);
+extern void intel_video_init(ScreenPtr pScreen);
+extern void intel_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b);
+extern void intel_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box);
-extern void I830InitVideo(ScreenPtr pScreen);
extern xf86CrtcPtr intel_covering_crtc(ScrnInfoPtr scrn, BoxPtr box,
xf86CrtcPtr desired, BoxPtr crtc_box_ret);
@@ -540,175 +474,16 @@ unsigned long intel_get_fence_pitch(inte
Bool intel_check_display_stride(ScrnInfoPtr scrn, int stride, Bool tiling);
void intel_set_gem_max_sizes(ScrnInfoPtr scrn);
+unsigned int
+intel_compute_size(struct intel_screen_private *intel,
+ int w, int h, int bpp, unsigned usage,
+ uint32_t *tiling, int *stride);
+
drm_intel_bo *intel_allocate_framebuffer(ScrnInfoPtr scrn,
int width, int height, int cpp,
int *out_stride,
uint32_t *out_tiling);
-/* i830_render.c */
-Bool i830_check_composite(int op,
- PicturePtr sourcec, PicturePtr mask, PicturePtr dest,
- int width, int height);
-Bool i830_check_composite_target(PixmapPtr pixmap);
-Bool i830_check_composite_texture(ScreenPtr screen, PicturePtr picture);
-Bool i830_prepare_composite(int op, PicturePtr sourcec, PicturePtr mask,
- PicturePtr dest, PixmapPtr sourcecPixmap,
- PixmapPtr maskPixmap, PixmapPtr destPixmap);
-void i830_composite(PixmapPtr dest, int srcX, int srcY,
- int maskX, int maskY, int dstX, int dstY, int w, int h);
-void i830_vertex_flush(intel_screen_private *intel);
-
-/* i915_render.c */
-Bool i915_check_composite(int op,
- PicturePtr sourcec, PicturePtr mask, PicturePtr dest,
- int width, int height);
-Bool i915_check_composite_target(PixmapPtr pixmap);
-Bool i915_check_composite_texture(ScreenPtr screen, PicturePtr picture);
-Bool i915_prepare_composite(int op, PicturePtr sourcec, PicturePtr mask,
- PicturePtr dest, PixmapPtr sourcecPixmap,
- PixmapPtr maskPixmap, PixmapPtr destPixmap);
-void i915_composite(PixmapPtr dest, int srcX, int srcY,
- int maskX, int maskY, int dstX, int dstY, int w, int h);
-void i915_vertex_flush(intel_screen_private *intel);
-void i915_batch_commit_notify(intel_screen_private *intel);
-void i830_batch_commit_notify(intel_screen_private *intel);
-/* i965_render.c */
-unsigned int gen4_render_state_size(ScrnInfoPtr scrn);
-void gen4_render_state_init(ScrnInfoPtr scrn);
-void gen4_render_state_cleanup(ScrnInfoPtr scrn);
-Bool i965_check_composite(int op,
- PicturePtr sourcec, PicturePtr mask, PicturePtr dest,
- int width, int height);
-Bool i965_check_composite_texture(ScreenPtr screen, PicturePtr picture);
-Bool i965_prepare_composite(int op, PicturePtr sourcec, PicturePtr mask,
- PicturePtr dest, PixmapPtr sourcecPixmap,
- PixmapPtr maskPixmap, PixmapPtr destPixmap);
-void i965_composite(PixmapPtr dest, int srcX, int srcY,
- int maskX, int maskY, int dstX, int dstY, int w, int h);
-
-void i965_vertex_flush(intel_screen_private *intel);
-void i965_batch_flush(intel_screen_private *intel);
-void i965_batch_commit_notify(intel_screen_private *intel);
-
-/* i965_3d.c */
-void gen6_upload_invariant_states(intel_screen_private *intel);
-void gen6_upload_viewport_state_pointers(intel_screen_private *intel,
- drm_intel_bo *cc_vp_bo);
-void gen7_upload_viewport_state_pointers(intel_screen_private *intel,
- drm_intel_bo *cc_vp_bo);
-void gen6_upload_urb(intel_screen_private *intel);
-void gen7_upload_urb(intel_screen_private *intel);
-void gen6_upload_cc_state_pointers(intel_screen_private *intel,
- drm_intel_bo *blend_bo, drm_intel_bo *cc_bo,
- drm_intel_bo *depth_stencil_bo,
- uint32_t blend_offset);
-void gen7_upload_cc_state_pointers(intel_screen_private *intel,
- drm_intel_bo *blend_bo, drm_intel_bo *cc_bo,
- drm_intel_bo *depth_stencil_bo,
- uint32_t blend_offset);
-void gen6_upload_sampler_state_pointers(intel_screen_private *intel,
- drm_intel_bo *sampler_bo);
-void gen7_upload_sampler_state_pointers(intel_screen_private *intel,
- drm_intel_bo *sampler_bo);
-void gen7_upload_bypass_states(intel_screen_private *intel);
-void gen6_upload_gs_state(intel_screen_private *intel);
-void gen6_upload_vs_state(intel_screen_private *intel);
-void gen6_upload_clip_state(intel_screen_private *intel);
-void gen6_upload_sf_state(intel_screen_private *intel, int num_sf_outputs, int read_offset);
-void gen7_upload_sf_state(intel_screen_private *intel, int num_sf_outputs, int read_offset);
-void gen6_upload_binding_table(intel_screen_private *intel, uint32_t ps_binding_table_offset);
-void gen7_upload_binding_table(intel_screen_private *intel, uint32_t ps_binding_table_offset);
-void gen6_upload_depth_buffer_state(intel_screen_private *intel);
-void gen7_upload_depth_buffer_state(intel_screen_private *intel);
-
-Bool intel_transform_is_affine(PictTransformPtr t);
-Bool
-intel_get_transformed_coordinates(int x, int y, PictTransformPtr transform,
- float *x_out, float *y_out);
-
-Bool
-intel_get_transformed_coordinates_3d(int x, int y, PictTransformPtr transform,
- float *x_out, float *y_out, float *z_out);
-
-static inline void
-intel_debug_fallback(ScrnInfoPtr scrn, const char *format, ...) _X_ATTRIBUTE_PRINTF(2, 3);
-
-static inline void
-intel_debug_fallback(ScrnInfoPtr scrn, const char *format, ...)
-{
- intel_screen_private *intel = intel_get_screen_private(scrn);
- va_list ap;
-
- va_start(ap, format);
- if (intel->fallback_debug) {
- xf86DrvMsg(scrn->scrnIndex, X_INFO, "fallback: ");
- LogVMessageVerb(X_INFO, 1, format, ap);
- }
- va_end(ap);
-}
-
-static inline Bool
-intel_check_pitch_2d(PixmapPtr pixmap)
-{
- uint32_t pitch = intel_pixmap_pitch(pixmap);
- if (pitch > KB(32)) {
- ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
- intel_debug_fallback(scrn, "pitch exceeds 2d limit 32K\n");
- return FALSE;
- }
- return TRUE;
-}
-
-/* For pre-965 chip only, as they have 8KB limit for 3D */
-static inline Bool
-intel_check_pitch_3d(PixmapPtr pixmap)
-{
- uint32_t pitch = intel_pixmap_pitch(pixmap);
- if (pitch > KB(8)) {
- ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
- intel_debug_fallback(scrn, "pitch exceeds 3d limit 8K\n");
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * Little wrapper around drm_intel_bo_reloc to return the initial value you
- * should stuff into the relocation entry.
- *
- * If only we'd done this before settling on the library API.
- */
-static inline uint32_t
-intel_emit_reloc(drm_intel_bo * bo, uint32_t offset,
- drm_intel_bo * target_bo, uint32_t target_offset,
- uint32_t read_domains, uint32_t write_domain)
-{
- drm_intel_bo_emit_reloc(bo, offset, target_bo, target_offset,
- read_domains, write_domain);
-
- return target_bo->offset + target_offset;
-}
-
-static inline drm_intel_bo *intel_bo_alloc_for_data(intel_screen_private *intel,
- const void *data,
- unsigned int size,
- const char *name)
-{
- drm_intel_bo *bo;
- int ret;
-
- bo = drm_intel_bo_alloc(intel->bufmgr, name, size, 4096);
- assert(bo);
-
- ret = drm_intel_bo_subdata(bo, 0, size, data);
- assert(ret == 0);
-
- return bo;
- (void)ret;
-}
-
-void intel_debug_flush(ScrnInfoPtr scrn);
-
static inline PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
{
ScreenPtr screen = drawable->pScreen;
@@ -726,18 +501,16 @@ static inline Bool pixmap_is_scanout(Pix
return pixmap == screen->GetScreenPixmap(screen);
}
-Bool intel_uxa_init(ScreenPtr pScreen);
-Bool intel_uxa_create_screen_resources(ScreenPtr pScreen);
-void intel_uxa_block_handler(intel_screen_private *intel);
-Bool intel_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table,
- int num_bos);
-
-static inline Bool intel_pixmap_is_offscreen(PixmapPtr pixmap)
+static inline int
+intel_pixmap_pitch(PixmapPtr pixmap)
{
- struct intel_pixmap *priv = intel_get_pixmap_private(pixmap);
- return priv && priv->offscreen;
+ return (unsigned long)pixmap->devKind;
}
+/*
+ * intel_sync.c
+ */
+
#if HAVE_DRI3
Bool intel_sync_init(ScreenPtr screen);
void intel_sync_close(ScreenPtr screen);
@@ -762,4 +535,13 @@ Bool intel_present_screen_init(ScreenPtr
static inline Bool intel_present_screen_init(ScreenPtr screen) { return 0; }
#endif
+dri_bo *
+intel_get_pixmap_bo(PixmapPtr pixmap);
+
+void
+intel_set_pixmap_bo(PixmapPtr pixmap, dri_bo *bo);
+
+void
+intel_flush(intel_screen_private *intel);
+
#endif /* _I830_H_ */