diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/ChangeLog xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/ChangeLog --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/ChangeLog 2015-03-04 15:55:36.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/ChangeLog 2015-03-18 16:55:03.000000000 +0000 @@ -1,9 +1,254 @@ -commit 9c1239844b8370079608ae6cb8e3d8b1c610ae34 +commit b0d73b7539d3a3ee58564d00f1f1f0616ddba070 Author: Robert Hooker -Date: Wed Mar 4 10:55:23 2015 -0500 +Date: Wed Mar 18 12:54:47 2015 -0400 Add debian tree from origin/ubuntu +commit bacaf7f18c2f4d3b5cb6bd6145dfb79fa4096759 +Author: Chris Wilson +Date: Tue Mar 17 09:45:09 2015 +0000 + + sna: Use struct pixman_f_vector for compatibility with older pixman + + Or else face compile failures: + + blt.c: In function 'affine_blt': + blt.c:1403:3: error: unknown type name 'pixman_f_vector_t' + blt.c:1407:4: error: request for member 'v' in something not a structure or union + blt.c:1408:4: error: request for member 'v' in something not a structure or union + blt.c:1409:4: error: request for member 'v' in something not a structure or union + blt.c:1411:3: warning: passing argument 2 of 'pixman_f_transform_point_3d' from incompatible pointer type [enabled by default] + In file included from /usr/include/xorg/miscstruct.h:52:0, + from /usr/include/xorg/regionstr.h:52, + from /usr/include/xorg/region.h:50, + from /usr/include/xorg/window.h:51, + from /usr/include/xorg/input.h:55, + from /usr/include/xorg/xf86str.h:38, + from sna.h:43, + from blt.c:32: + /usr/include/pixman-1/pixman.h:247:15: note: expected 'struct pixman_f_vector *' but argument is of type 'int *' + blt.c:1413:7: error: request for member 'v' in something not a structure or union + blt.c:1415:7: error: request for member 'v' in something not a structure or union + + Signed-off-by: Chris Wilson + +commit 9d0d78230aaf8863a96d75e8b57bb62e51121b8a +Author: Chris Wilson +Date: Fri Mar 13 23:07:59 2015 +0000 + + sna: Skip inplace operation to a busy clear GPU bo + + Since clearing is a relatively trivial operation, allow us to do the + clear to a CPU bo rather than block on the GPU. + + Signed-off-by: Chris Wilson + +commit d8dd2b88a1f2bca63a2a6f42af035fd9fb1f685f +Author: Chris Wilson +Date: Fri Mar 13 22:27:31 2015 +0000 + + sna/gen6+: Demote BLT ring switching priority if semaphores are disabled + + Signed-off-by: Chris Wilson + +commit 66cb6c23d110300fff0235fd07408362e8491339 +Author: Chris Wilson +Date: Fri Mar 13 15:44:44 2015 +0000 + + sna: Start demoting some assertions + + A few assertions are there to catch less desirable behaviour rather than + outright errors. For these, just grab the backtrace and continue. + + Signed-off-by: Chris Wilson + +commit 7863efebf5bee0dbdad55e5402e02413e26f7a4f +Author: Chris Wilson +Date: Fri Mar 13 15:21:47 2015 +0000 + + sna/gen6+: Relax assertions in light of !semaphores + + Signed-off-by: Chris Wilson + +commit 359f12312ece78333162eb8fd191968a4b0030b6 +Author: Chris Wilson +Date: Fri Mar 13 15:21:26 2015 +0000 + + sna: Fix assertions for transformed cursors + + Signed-off-by: Chris Wilson + +commit c2381ac065e0d7fc39ae029045eda54b36766324 +Author: Chris Wilson +Date: Fri Mar 13 14:39:56 2015 +0000 + + sna: Remove redundant RRGetInfo on hotplug discovery + + Signed-off-by: Chris Wilson + +commit 2f1fb20d89b032f56737530ade3a22564e08cf4d +Author: Chris Wilson +Date: Fri Mar 13 13:14:27 2015 +0000 + + sna: Explicitly compute whether the transform is affine for HW cursors + + Signed-off-by: Chris Wilson + +commit bc84ba6f97b2cdd5d9f2d0c4b5c7b6532ed5d0e6 +Author: Chris Wilson +Date: Fri Mar 13 12:12:21 2015 +0000 + + sna: Fix computation of transformed cursor size + + Signed-off-by: Chris Wilson + +commit 557ffa3bacd8e673fe8d4f141a74b037eb9de095 +Author: Chris Wilson +Date: Fri Mar 13 12:08:04 2015 +0000 + + sna: Cross check that we only have an affine transformation for HW cursors + + Signed-off-by: Chris Wilson + +commit d867d48bb63273e72d45baaaf53cb23f0e493de5 +Author: Chris Wilson +Date: Thu Mar 12 22:29:29 2015 +0000 + + sna: Apply affine transformations to HW cursors + + Until now we only applied pixel-exact rotations to the cursors. However, + this left the cursors ignoring scaling and so appearing incorrect on + outputs with transformations applied. An extra complications comes from + making sure that the scaling routine is signal safe. + + Signed-off-by: Chris Wilson + +commit 56ebdb7d95a9da8fb66ae82d3f546d15bd89b5a6 +Author: Chris Wilson +Date: Thu Mar 12 14:27:59 2015 +0000 + + sna: Disable hw cursor when random transforms are applied + + Ideally, we would iterate over each CRTC and check that the transformed + cursor is still valid for the HW plane and then remember to transform + the cursor before displaying. Disabling the HW cursor if a non-native + transform is the first step in correcting the display of said cursor. + + Signed-off-by: Chris Wilson + +commit 341654dc276d254aa23593efdb8e4c27a9ca1f77 +Author: Chris Wilson +Date: Thu Mar 12 13:50:39 2015 +0000 + + sna: Compute half resolution modes + + Sitting here with a 3200x1600 panel but no 1600x900 intermediate mode, + and I am too lazy to add it by hand. + + Signed-off-by: Chris Wilson + +commit 71318389bedc87d3a2ea386343c371e5caed2880 +Author: Chris Wilson +Date: Thu Mar 12 12:39:55 2015 +0000 + + sna: Futureproof acceleration backend selection + + Signed-off-by: Chris Wilson + +commit 15c307d70e00bc035bb61be5d8b6f727925e3d34 +Author: Chris Wilson +Date: Tue Mar 10 08:48:48 2015 +0000 + + sna: Force frontbuffer to CPU for randr fallback + + When we are using the fallback method, we need to make sure the source + is on the CPU. + + Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89053 + Signed-off-by: Chris Wilson + +commit 535b030c02c3769dbf537babb686a03544d9e8a3 +Author: Chris Wilson +Date: Mon Mar 9 16:33:06 2015 +0000 + + sna: Strengthen assertions that batches are idle before overwriting + + Signed-off-by: Chris Wilson + +commit f7c4bc7c5f5a194e1794644c0641eb735f97b297 +Author: Chris Wilson +Date: Sat Mar 7 21:09:39 2015 +0000 + + sna/gen6+: Demote priority of COPY_LAST for copy boxes + + Even if we expect to flush at the end of the operation, we still want to + consider semaphores before overriding the engine selection. + + Signed-off-by: Chris Wilson + +commit aefedd2baff8beaa5a5548bcf7a126ab6fca310b +Author: Chris Wilson +Date: Sat Mar 7 10:58:53 2015 +0000 + + sna/gen6+: Prefer the BLT for small copies + + Signed-off-by: Chris Wilson + +commit 8e8eac509731747f1076bcaf1cbadac1b6daca0b +Author: Chris Wilson +Date: Fri Mar 6 09:11:11 2015 +0000 + + tools/cursor: Inlcude stdlib for malloc declaration + + Signed-off-by: Chris Wilson + +commit 6522fedaa1023939c046fb6e9a1d2f48d30a37c8 +Author: Chris Wilson +Date: Thu Mar 5 14:18:07 2015 +0000 + + sna/dri2: Don't dereference a NULL drawable on client shutdown whilst flipping + + A dropped if(!NULL) check from the previous patch. + + Signed-off-by: Chris Wilson + +commit 72d208a7f2f0e8f2d93483e535154f34a8a26d81 +Author: Chris Wilson +Date: Thu Mar 5 12:26:15 2015 +0000 + + sna/dri2: Perform swap elision on windows for swap-interval==0 + + In order to be more like Windows and inflate benchmark results. + + Signed-off-by: Chris Wilson + +commit 7ae299be60ef3ab4f8cc49edd9d5a14d826d5583 +Author: Chris Wilson +Date: Thu Mar 5 08:39:31 2015 +0000 + + sna: Remove the flush after waking up between clients + + In the normal command processing stream, we will have lots of + opportunity to ask whether we should be batching requests together. If + we wakeup without doing any work, then we will check inside the block + handler whether the GPU is idle and flush then. + + Signed-off-by: Chris Wilson + +commit db82617464e55432522e6199a88408ff0187f6ff +Author: Chris Wilson +Date: Wed Mar 4 17:12:30 2015 +0000 + + sna: Decouple RandR pointers early in CloseScreen + + RR resources are freed before CloseScreen (as they are a ServerClient + resource), but on entering our CloseScreen callbacks we are left with a + set of stale pointers. Decouple those before proceeding so that we are + not tempted to dereference them. + + Bugzilla: https://bugs.archlinux.org/task/43906 + Signed-off-by: Chris Wilson + commit 88e615425bd61856c3f039127fb90592dfac22df Author: Chris Wilson Date: Wed Mar 4 15:28:49 2015 +0000 diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/configure xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/configure --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/configure 2015-03-04 15:55:33.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/configure 2015-03-18 16:54:59.000000000 +0000 @@ -20472,6 +20472,7 @@ fi ABI_VERSION=`$PKG_CONFIG --variable=abi_videodrv xorg-server` XSERVER_VERSION=`$PKG_CONFIG --modversion xorg-server` +PIXMAN_VERSION=`$PKG_CONFIG --modversion pixman-1` if test "x$ONLY_UMS" = "xyes"; then UMS="yes" @@ -24390,6 +24391,7 @@ echo "" echo "xf86-video-intel 2.99.917 will be compiled with:" echo " Xorg Video ABI version: $ABI_VERSION (xorg-server-$XSERVER_VERSION)" +echo " pixman version: pixman-1-$PIXMAN_VERSION" echo " Acceleration backends:$accel_msg" echo " Additional debugging support?$debug_msg" echo " Support for Kernel Mode Setting? $KMS" diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/configure.ac xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/configure.ac --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/configure.ac 2015-03-04 15:55:22.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/configure.ac 2015-03-18 16:54:47.000000000 +0000 @@ -447,6 +447,7 @@ PKG_CHECK_MODULES(XORG, [xorg-server >= $required_xorg_server_version xproto fontsproto pixman-1 >= $required_pixman_version $REQUIRED_MODULES]) ABI_VERSION=`$PKG_CONFIG --variable=abi_videodrv xorg-server` XSERVER_VERSION=`$PKG_CONFIG --modversion xorg-server` +PIXMAN_VERSION=`$PKG_CONFIG --modversion pixman-1` if test "x$ONLY_UMS" = "xyes"; then UMS="yes" @@ -914,6 +915,7 @@ echo "" echo "AC_PACKAGE_STRING will be compiled with:" echo " Xorg Video ABI version: $ABI_VERSION (xorg-server-$XSERVER_VERSION)" +echo " pixman version: pixman-1-$PIXMAN_VERSION" echo " Acceleration backends:$accel_msg" echo " Additional debugging support?$debug_msg" echo " Support for Kernel Mode Setting? $KMS" diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/debian/changelog xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/debian/changelog --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/debian/changelog 2015-03-18 16:57:16.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/debian/changelog 2015-03-18 16:57:17.000000000 +0000 @@ -1,12 +1,12 @@ -xserver-xorg-video-intel (2:2.99.917+git20150304.88e61542-0ubuntu0sarvatt) vivid; urgency=high +xserver-xorg-video-intel (2:2.99.917+git20150318.bacaf7f1-0ubuntu0sarvatt) vivid; urgency=high - * Checkout from git 20150304 (master branch) up to commit - 88e615425bd61856c3f039127fb90592dfac22df + * Checkout from git 20150318 (master branch) up to commit + bacaf7f18c2f4d3b5cb6bd6145dfb79fa4096759 * Only added debian/ tree from origin/ubuntu * hook: Drop xmir.patch (fails) * hook: Drop fix-sna-external-slave-rotation.patch (upstream) - -- Robert Hooker Wed, 04 Mar 2015 10:55:36 -0500 + -- Robert Hooker Wed, 18 Mar 2015 12:55:03 -0400 xserver-xorg-video-intel (2:2.99.917-1~exp1ubuntu2) vivid; urgency=medium diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/.lastcommit xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/.lastcommit --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/.lastcommit 2015-03-04 15:55:22.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/.lastcommit 2015-03-18 16:54:47.000000000 +0000 @@ -1 +1 @@ -commit 88e615425bd61856c3f039127fb90592dfac22df +commit bacaf7f18c2f4d3b5cb6bd6145dfb79fa4096759 diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/blt.c xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/blt.c --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/blt.c 2015-03-04 15:55:22.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/blt.c 2015-03-18 16:54:47.000000000 +0000 @@ -30,6 +30,7 @@ #endif #include "sna.h" +#include #if __x86_64__ #define USE_SSE2 1 @@ -1240,3 +1241,241 @@ } } } + +#define BILINEAR_INTERPOLATION_BITS 4 +static force_inline int +bilinear_weight(pixman_fixed_t x) +{ + return (x >> (16 - BILINEAR_INTERPOLATION_BITS)) & + ((1 << BILINEAR_INTERPOLATION_BITS) - 1); +} + +#if BILINEAR_INTERPOLATION_BITS <= 4 +/* Inspired by Filter_32_opaque from Skia */ +static force_inline uint32_t +bilinear_interpolation(uint32_t tl, uint32_t tr, + uint32_t bl, uint32_t br, + int distx, int disty) +{ + int distxy, distxiy, distixy, distixiy; + uint32_t lo, hi; + + distx <<= (4 - BILINEAR_INTERPOLATION_BITS); + disty <<= (4 - BILINEAR_INTERPOLATION_BITS); + + distxy = distx * disty; + distxiy = (distx << 4) - distxy; /* distx * (16 - disty) */ + distixy = (disty << 4) - distxy; /* disty * (16 - distx) */ + distixiy = + 16 * 16 - (disty << 4) - + (distx << 4) + distxy; /* (16 - distx) * (16 - disty) */ + + lo = (tl & 0xff00ff) * distixiy; + hi = ((tl >> 8) & 0xff00ff) * distixiy; + + lo += (tr & 0xff00ff) * distxiy; + hi += ((tr >> 8) & 0xff00ff) * distxiy; + + lo += (bl & 0xff00ff) * distixy; + hi += ((bl >> 8) & 0xff00ff) * distixy; + + lo += (br & 0xff00ff) * distxy; + hi += ((br >> 8) & 0xff00ff) * distxy; + + return ((lo >> 8) & 0xff00ff) | (hi & ~0xff00ff); +} +#elif SIZEOF_LONG > 4 +static force_inline uint32_t +bilinear_interpolation(uint32_t tl, uint32_t tr, + uint32_t bl, uint32_t br, + int distx, int disty) +{ + uint64_t distxy, distxiy, distixy, distixiy; + uint64_t tl64, tr64, bl64, br64; + uint64_t f, r; + + distx <<= (8 - BILINEAR_INTERPOLATION_BITS); + disty <<= (8 - BILINEAR_INTERPOLATION_BITS); + + distxy = distx * disty; + distxiy = distx * (256 - disty); + distixy = (256 - distx) * disty; + distixiy = (256 - distx) * (256 - disty); + + /* Alpha and Blue */ + tl64 = tl & 0xff0000ff; + tr64 = tr & 0xff0000ff; + bl64 = bl & 0xff0000ff; + br64 = br & 0xff0000ff; + + f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy; + r = f & 0x0000ff0000ff0000ull; + + /* Red and Green */ + tl64 = tl; + tl64 = ((tl64 << 16) & 0x000000ff00000000ull) | (tl64 & 0x0000ff00ull); + + tr64 = tr; + tr64 = ((tr64 << 16) & 0x000000ff00000000ull) | (tr64 & 0x0000ff00ull); + + bl64 = bl; + bl64 = ((bl64 << 16) & 0x000000ff00000000ull) | (bl64 & 0x0000ff00ull); + + br64 = br; + br64 = ((br64 << 16) & 0x000000ff00000000ull) | (br64 & 0x0000ff00ull); + + f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy; + r |= ((f >> 16) & 0x000000ff00000000ull) | (f & 0xff000000ull); + + return (uint32_t)(r >> 16); +} +#else +static force_inline uint32_t +bilinear_interpolation(uint32_t tl, uint32_t tr, + uint32_t bl, uint32_t br, + int distx, int disty) +{ + int distxy, distxiy, distixy, distixiy; + uint32_t f, r; + + distx <<= (8 - BILINEAR_INTERPOLATION_BITS); + disty <<= (8 - BILINEAR_INTERPOLATION_BITS); + + distxy = distx * disty; + distxiy = (distx << 8) - distxy; /* distx * (256 - disty) */ + distixy = (disty << 8) - distxy; /* disty * (256 - distx) */ + distixiy = + 256 * 256 - (disty << 8) - + (distx << 8) + distxy; /* (256 - distx) * (256 - disty) */ + + /* Blue */ + r = ((tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy + + (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy); + + /* Green */ + f = ((tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy + + (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy); + r |= f & 0xff000000; + + tl >>= 16; + tr >>= 16; + bl >>= 16; + br >>= 16; + r >>= 16; + + /* Red */ + f = ((tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy + + (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy); + r |= f & 0x00ff0000; + + /* Alpha */ + f = ((tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy + + (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy); + r |= f & 0xff000000; + + return r; +} +#endif + +static inline uint32_t convert_pixel(const uint8_t *p, int x) +{ + return ((uint32_t *)p)[x]; +} + +fast void +affine_blt(const void *src, void *dst, int bpp, + int16_t src_x, int16_t src_y, + int16_t src_width, int16_t src_height, + int32_t src_stride, + int16_t dst_x, int16_t dst_y, + uint16_t dst_width, uint16_t dst_height, + int32_t dst_stride, + const struct pixman_f_transform *t) +{ + static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + const pixman_fixed_t ux = pixman_double_to_fixed(t->m[0][0]); + const pixman_fixed_t uy = pixman_double_to_fixed(t->m[1][0]); + int i, j; + + assert(bpp == 32); + + for (j = 0; j < dst_height; j++) { + pixman_fixed_t x, y; + struct pixman_f_vector v; + uint32_t *b; + + /* reference point is the center of the pixel */ + v.v[0] = dst_x + 0.5; + v.v[1] = dst_y + j + 0.5; + v.v[2] = 1.0; + + pixman_f_transform_point_3d(t, &v); + + x = pixman_double_to_fixed(v.v[0]); + x += pixman_int_to_fixed(src_x - dst_x); + y = pixman_double_to_fixed(v.v[1]); + y += pixman_int_to_fixed(src_y - dst_y); + + b = (uint32_t*)((uint8_t *)dst + (dst_y + j) * dst_stride + dst_x * bpp / 8); + for (i = 0; i < dst_width; i++) { + const uint8_t *row1; + const uint8_t *row2; + int x1, y1, x2, y2; + uint32_t tl, tr, bl, br; + int32_t fx, fy; + + x1 = x - pixman_fixed_1/2; + y1 = y - pixman_fixed_1/2; + + fx = bilinear_weight(x1); + fy = bilinear_weight(y1); + + x1 = pixman_fixed_to_int(x1); + x2 = x1 + 1; + y1 = pixman_fixed_to_int(y1); + y2 = y1 + 1; + + if (x1 >= src_width || x2 < 0 || + y1 >= src_height || y2 < 0) { + b[i] = 0; + goto next; + } + + if (y2 == 0) { + row1 = zero; + } else { + row1 = (uint8_t *)src + src_stride * y1; + row1 += bpp / 8 * x1; + } + + if (y1 == src_height - 1) { + row2 = zero; + } else { + row2 = (uint8_t *)src + src_stride * y2; + row2 += bpp / 8 * x1; + } + + if (x2 == 0) { + tl = 0; + bl = 0; + } else { + tl = convert_pixel(row1, 0); + bl = convert_pixel(row2, 0); + } + + if (x1 == src_width - 1) { + tr = 0; + br = 0; + } else { + tr = convert_pixel(row1, 1); + br = convert_pixel(row2, 1); + } + + b[i] = bilinear_interpolation(tl, tr, bl, br, fx, fy); + +next: + x += ux; + y += uy; + } + } +} diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/gen6_common.h xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/gen6_common.h --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/gen6_common.h 2015-03-04 15:55:22.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/gen6_common.h 2015-03-18 16:54:47.000000000 +0000 @@ -49,9 +49,6 @@ if (NO_RING_SWITCH(sna)) return false; - if (flags & COPY_LAST) - return true; - if (bo && RQ_IS_BLT(bo->rq)) return true; @@ -61,6 +58,9 @@ if (bo && RQ_IS_RENDER(bo->rq)) return false; + if (flags & COPY_LAST) + return true; + return kgem_ring_is_idle(&sna->kgem, KGEM_BLT); } @@ -106,12 +106,15 @@ inline static bool force_blt_ring(struct sna *sna) { - if (sna->flags & SNA_POWERSAVE) - return true; - if (sna->kgem.mode == KGEM_RENDER) return false; + if (NO_RING_SWITCH(sna)) + return sna->kgem.ring == KGEM_BLT; + + if (sna->flags & SNA_POWERSAVE) + return true; + if (sna->render_state.gt < 2) return true; @@ -125,7 +128,7 @@ return PREFER_RENDER < 0; assert(!force_blt_ring(sna)); - assert(!kgem_bo_is_render(bo)); + assert(!kgem_bo_is_render(bo) || NO_RING_SWITCH(sna)); if (kgem_bo_is_blt(bo)) return true; diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/gen6_render.c xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/gen6_render.c --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/gen6_render.c 2015-03-04 15:55:22.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/gen6_render.c 2015-03-18 16:54:47.000000000 +0000 @@ -2694,6 +2694,10 @@ kgem_bo_is_render(src_bo)) return false; + if (flags & COPY_LAST && + can_switch_to_blt(sna, dst_bo, flags)) + return true; + if (prefer_render_ring(sna, dst_bo)) return false; diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/gen7_render.c xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/gen7_render.c --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/gen7_render.c 2015-03-04 15:55:22.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/gen7_render.c 2015-03-18 16:54:47.000000000 +0000 @@ -2897,6 +2897,10 @@ kgem_bo_is_render(src_bo)) return false; + if (flags & COPY_LAST && + can_switch_to_blt(sna, dst_bo, flags)) + return true; + if (prefer_render_ring(sna, dst_bo)) return false; diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/gen8_render.c xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/gen8_render.c --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/gen8_render.c 2015-03-04 15:55:22.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/gen8_render.c 2015-03-18 16:54:47.000000000 +0000 @@ -2720,6 +2720,10 @@ kgem_bo_is_render(src_bo)) return false; + if (flags & COPY_LAST && + can_switch_to_blt(sna, dst_bo, flags)) + return true; + if (prefer_render_ring(sna, dst_bo)) return false; diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/kgem.c xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/kgem.c --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/kgem.c 2015-03-04 15:55:22.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/kgem.c 2015-03-18 16:54:47.000000000 +0000 @@ -3249,7 +3249,9 @@ char *ptr; int ret; - ASSERT_IDLE(kgem, bo->handle); + assert(bo->exec == NULL); + assert(bo->rq == NULL); + assert(!__kgem_busy(kgem, bo->handle)); #if DBG_NO_EXEC { @@ -6259,8 +6261,8 @@ 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); + warn_unless(num_pages(bo) <= kgem->aperture_mappable / 2); ptr = bo->map__gtt; if (ptr == NULL) diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/sna_accel.c xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/sna_accel.c --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/sna_accel.c 2015-03-04 15:55:22.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/sna_accel.c 2015-03-18 16:54:47.000000000 +0000 @@ -527,10 +527,10 @@ DBG(("%s: allocating CPU buffer (%dx%d)\n", __FUNCTION__, pixmap->drawable.width, pixmap->drawable.height)); - hint = 0; - if ((flags & MOVE_ASYNC_HINT) == 0 && - ((flags & MOVE_READ) == 0 || (priv->gpu_damage && !priv->clear && !sna->kgem.has_llc))) - hint = CREATE_CPU_MAP | CREATE_INACTIVE | CREATE_NO_THROTTLE; + hint = CREATE_CPU_MAP | CREATE_INACTIVE | CREATE_NO_THROTTLE; + if ((flags & MOVE_ASYNC_HINT) || + (priv->gpu_damage && !priv->clear && kgem_bo_is_busy(priv->gpu_bo) && sna->kgem.can_blt_cpu)) + hint = 0; priv->cpu_bo = kgem_create_cpu_2d(&sna->kgem, pixmap->drawable.width, @@ -1582,6 +1582,16 @@ return false; if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo)) { + if (priv->clear) { + DBG(("%s: no, clear GPU bo is busy\n", __FUNCTION__)); + return false; + } + + if (flags & MOVE_ASYNC_HINT) { + DBG(("%s: no, async hint and GPU bo is busy\n", __FUNCTION__)); + return false; + } + if ((flags & (MOVE_WRITE | MOVE_READ)) == (MOVE_WRITE | MOVE_READ)) { DBG(("%s: no, GPU bo is busy\n", __FUNCTION__)); return false; @@ -2274,6 +2284,7 @@ (flags & MOVE_WRITE ? (void *)priv->gpu_bo : (void *)priv->gpu_damage) && priv->cpu_damage == NULL && priv->gpu_bo->tiling == I915_TILING_NONE && (flags & MOVE_READ || kgem_bo_can_map__cpu(&sna->kgem, priv->gpu_bo, flags & MOVE_WRITE)) && + (!priv->clear || !kgem_bo_is_busy(priv->gpu_bo)) && ((flags & (MOVE_WRITE | MOVE_ASYNC_HINT)) == 0 || (!priv->cow && !priv->move_to_gpu && !__kgem_bo_is_busy(&sna->kgem, priv->gpu_bo)))) { void *ptr; @@ -2337,6 +2348,7 @@ pixmap->devKind, pixmap->devKind * pixmap->drawable.height)); if (priv->cpu_bo) { + kgem_bo_undo(&sna->kgem, priv->cpu_bo); if ((flags & MOVE_ASYNC_HINT || priv->cpu_bo->exec) && sna->kgem.can_blt_cpu && sna->render.fill_one(sna, @@ -17849,6 +17861,9 @@ if (xf86ReturnOptValBool(sna->Options, OPTION_ACCEL_DISABLE, FALSE)) return true; + if (sna->kgem.gen >= 0120) + return true; + if (!intel_option_cast_to_bool(sna->Options, OPTION_ACCEL_METHOD, !IS_DEFAULT_ACCEL_METHOD(NOACCEL))) @@ -17869,6 +17884,9 @@ { const char *s; + if (sna->kgem.gen >= 0110) + return true; + s = xf86GetOptValString(sna->Options, OPTION_ACCEL_METHOD); if (s == NULL) return false; @@ -17957,21 +17975,21 @@ backend = "disabled"; sna->kgem.wedged = true; sna_render_mark_wedged(sna); - } else if (sna_option_accel_blt(sna) || sna->info->gen >= 0110) + } else if (sna_option_accel_blt(sna)) (void)backend; - else if (sna->info->gen >= 0100) + else if (sna->kgem.gen >= 0100) backend = gen8_render_init(sna, backend); - else if (sna->info->gen >= 070) + else if (sna->kgem.gen >= 070) backend = gen7_render_init(sna, backend); - else if (sna->info->gen >= 060) + else if (sna->kgem.gen >= 060) backend = gen6_render_init(sna, backend); - else if (sna->info->gen >= 050) + else if (sna->kgem.gen >= 050) backend = gen5_render_init(sna, backend); - else if (sna->info->gen >= 040) + else if (sna->kgem.gen >= 040) backend = gen4_render_init(sna, backend); - else if (sna->info->gen >= 030) + else if (sna->kgem.gen >= 030) backend = gen3_render_init(sna, backend); - else if (sna->info->gen >= 020) + else if (sna->kgem.gen >= 020) backend = gen2_render_init(sna, backend); DBG(("%s(backend=%s, prefer_gpu=%x)\n", @@ -18068,7 +18086,7 @@ kgem_cleanup_cache(&sna->kgem); } -void sna_accel_block_handler(struct sna *sna, struct timeval **tv) +void sna_accel_block(struct sna *sna, struct timeval **tv) { sigtrap_assert_inactive(); @@ -18148,22 +18166,6 @@ } } -void sna_accel_wakeup_handler(struct sna *sna) -{ - DBG(("%s: nbatch=%d, need_retire=%d, need_purge=%d\n", __FUNCTION__, - sna->kgem.nbatch, sna->kgem.need_retire, sna->kgem.need_purge)); - - if (!sna->kgem.nbatch) - return; - - if (kgem_is_idle(&sna->kgem)) { - DBG(("%s: GPU idle, flushing\n", __FUNCTION__)); - _kgem_submit(&sna->kgem); - } - - sigtrap_assert_inactive(); -} - void sna_accel_free(struct sna *sna) { DBG(("%s\n", __FUNCTION__)); diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/sna_display.c xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/sna_display.c --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/sna_display.c 2015-03-04 15:55:22.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/sna_display.c 2015-03-18 16:54:47.000000000 +0000 @@ -116,6 +116,20 @@ extern XF86ConfigPtr xf86configptr; +struct sna_cursor { + struct sna_cursor *next; + uint32_t *image; + bool transformed; + Rotation rotation; + int ref; + int size; + int last_width; + int last_height; + unsigned handle; + unsigned serial; + unsigned alloc; +}; + struct sna_crtc { xf86CrtcPtr base; struct drm_mode_modeinfo kmode; @@ -128,6 +142,8 @@ bool shadow; bool fallback_shadow; bool transform; + bool cursor_transform; + bool hwcursor; bool flip_pending; uint8_t id; uint8_t pipe; @@ -1582,6 +1598,8 @@ sna_crtc->transform = false; } + sna_crtc->cursor_transform = false; + sna_crtc->hwcursor = true; assert(!sna_crtc->shadow); } @@ -2194,6 +2212,37 @@ } } +#define SCALING_EPSILON (1./256) + +static bool +is_affine(const struct pixman_f_transform *t) +{ + return (fabs(t->m[2][0]) < SCALING_EPSILON && + fabs(t->m[2][1]) < SCALING_EPSILON); +} + +static double determinant(const struct pixman_f_transform *t) +{ + return t->m[0][0]*t->m[1][1] - t->m[1][0]*t->m[0][1]; +} + +static bool +affine_is_pixel_exact(const struct pixman_f_transform *t) +{ + double det = t->m[2][2] * determinant(t); + if (fabs (det * det - 1.0) < SCALING_EPSILON) { + if (fabs(t->m[0][1]) < SCALING_EPSILON && + fabs(t->m[1][0]) < SCALING_EPSILON) + return true; + + if (fabs(t->m[0][0]) < SCALING_EPSILON && + fabs(t->m[1][1]) < SCALING_EPSILON) + return true; + } + + return false; +} + static void sna_crtc_randr(xf86CrtcPtr crtc) { struct sna_crtc *sna_crtc = to_sna_crtc(crtc); @@ -2239,6 +2288,16 @@ } else crtc->transform_in_use = sna_crtc->rotation != RR_Rotate_0; + if (needs_transform) { + sna_crtc->hwcursor = is_affine(&f_fb_to_crtc); + sna_crtc->cursor_transform = + sna_crtc->hwcursor && + !affine_is_pixel_exact(&f_fb_to_crtc); + } else { + sna_crtc->hwcursor = true; + sna_crtc->cursor_transform = false; + } + crtc->crtc_to_framebuffer = crtc_to_fb; crtc->f_crtc_to_framebuffer = f_crtc_to_fb; crtc->f_framebuffer_to_crtc = f_fb_to_crtc; @@ -2361,6 +2420,8 @@ struct kgem_bo *saved_bo, *bo; uint32_t saved_offset; bool saved_transform; + bool saved_hwcursor; + bool saved_cursor_transform; DBG(("%s: CRTC=%d, pipe=%d, hidden?=%d\n", __FUNCTION__, sna_crtc->id, sna_crtc->pipe, sna->mode.hidden)); @@ -2369,6 +2430,8 @@ saved_bo = sna_crtc->bo; saved_transform = sna_crtc->transform; + saved_cursor_transform = sna_crtc->cursor_transform; + saved_hwcursor = sna_crtc->hwcursor; saved_offset = sna_crtc->offset; sna_crtc->fallback_shadow = false; @@ -2414,6 +2477,12 @@ sna_crtc_randr(crtc); if (sna_crtc->transform) sna_crtc_damage(crtc); + if (sna_crtc->cursor && /* Reload cursor if RandR maybe changed */ + (!sna_crtc->hwcursor || + saved_cursor_transform || sna_crtc->cursor_transform || + sna_crtc->cursor->rotation != crtc->rotation)) + sna_crtc_disable_cursor(sna, sna_crtc); + assert(!sna->mode.hidden); sna->mode.front_active += saved_bo == NULL; sna->mode.dirty = true; @@ -2431,6 +2500,8 @@ if (saved_transform) sna->mode.rr_active++; sna_crtc->transform = saved_transform; + sna_crtc->cursor_transform = saved_cursor_transform; + sna_crtc->hwcursor = saved_hwcursor; sna_crtc->bo = saved_bo; sna_mode_discover(sna); return FALSE; @@ -3100,14 +3171,49 @@ } } +static bool duplicate_mode(DisplayModePtr modes, DisplayModePtr m) +{ + if (m == NULL) + return false; + + while (modes) { + if (xf86ModesEqual(modes, m)) + return true; + + modes = modes->next; + } + + return false; +} + static DisplayModePtr -default_modes(void) +default_modes(DisplayModePtr preferred) { + DisplayModePtr modes; + #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,900,0) - return xf86GetDefaultModes(); + modes = xf86GetDefaultModes(); #else - return xf86GetDefaultModes(0, 0); + modes = xf86GetDefaultModes(0, 0); #endif + +#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,4,99,901,0) + if (preferred) { + DisplayModePtr m; + + /* Add a half-resolution mode useful for large panels */ + m = xf86GTFMode(preferred->HDisplay/2, + preferred->VDisplay/2, + xf86ModeVRefresh(preferred), + FALSE, FALSE); + if (!duplicate_mode(modes, m)) + modes = xf86ModesAdd(modes, m); + else + free(m); + } +#endif + + return modes; } static DisplayModePtr @@ -3132,7 +3238,7 @@ max_vrefresh = max(max_vrefresh, 60.0); max_vrefresh *= (1 + SYNC_TOLERANCE); - m = default_modes(); + m = default_modes(preferred); xf86ValidateModesSize(output->scrn, m, max_x, max_y, 0); for (i = m; i; i = i->next) { @@ -4354,8 +4460,11 @@ continue; sna_output->last_detect = 0; - if (sna_output->serial == serial) + if (sna_output->serial == serial) { + if (sna_output_detect(output) != output->status) + RROutputChanged(output->randr_output, TRUE); continue; + } DBG(("%s: removing output %s (id=%d), serial=%u [now %u]\n", __FUNCTION__, output->name, sna_output->id, @@ -4390,6 +4499,8 @@ xf86RandR12TellChanged(screen); } + + RRTellChanged(screen); } static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new) @@ -4586,19 +4697,6 @@ } /* cursor handling */ -struct sna_cursor { - struct sna_cursor *next; - uint32_t *image; - Rotation rotation; - int ref; - int size; - int last_width; - int last_height; - unsigned handle; - unsigned serial; - unsigned alloc; -}; - static void rotate_coord(Rotation rotation, int size, int x_dst, int y_dst, @@ -4724,6 +4822,17 @@ #endif } +static int __cursor_size(int width, int height) +{ + int i, size; + + i = MAX(width, height); + for (size = 64; size < i; size <<= 1) + ; + + return size; +} + static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc) { struct sna_cursor *cursor; @@ -4731,6 +4840,9 @@ const uint32_t *argb; uint32_t *image; int width, height, pitch, size, x, y; + PictTransform cursor_to_fb; + struct pict_f_transform f_cursor_to_fb, f_fb_to_cursor; + bool transformed; Rotation rotation; assert(sna->cursor.ref); @@ -4742,8 +4854,8 @@ cursor ? cursor->serial : 0, sna->cursor.serial)); if (cursor && cursor->serial == sna->cursor.serial) { - assert(cursor->size == sna->cursor.size); - assert(cursor->rotation == crtc->transform_in_use ? crtc->rotation : RR_Rotate_0); + assert(cursor->size == sna->cursor.size || cursor->transformed); + assert(cursor->rotation == (!to_sna_crtc(crtc)->cursor_transform && crtc->transform_in_use) ? crtc->rotation : RR_Rotate_0); assert(cursor->ref); return cursor; } @@ -4755,11 +4867,15 @@ sna->cursor.serial, get_cursor_argb(sna->cursor.ref) != NULL)); - rotation = crtc->transform_in_use ? crtc->rotation : RR_Rotate_0; + transformed = to_sna_crtc(crtc)->cursor_transform; + rotation = (!transformed && crtc->transform_in_use) ? crtc->rotation : RR_Rotate_0; - if (sna->cursor.use_gtt) { /* Don't allow phys cursor sharing */ + /* Don't allow phys cursor sharing */ + if (sna->cursor.use_gtt && !transformed) { for (cursor = sna->cursor.cursors; cursor; cursor = cursor->next) { - if (cursor->serial == sna->cursor.serial && cursor->rotation == rotation) { + if (cursor->serial == sna->cursor.serial && + cursor->rotation == rotation && + !cursor->transformed) { __DBG(("%s: reusing handle=%d, serial=%d, rotation=%d, size=%d\n", __FUNCTION__, cursor->handle, cursor->serial, cursor->rotation, cursor->size)); assert(cursor->size == sna->cursor.size); @@ -4768,7 +4884,26 @@ } } - size = sna->cursor.size; + if (transformed) { + struct pixman_box16 box; + + box.x1 = box.y1 = 0; + box.x2 = sna->cursor.ref->bits->width; + box.y2 = sna->cursor.ref->bits->height; + + pixman_f_transform_bounds(&crtc->f_crtc_to_framebuffer, &box); + size = __cursor_size(box.x2 - box.x1, box.y2 - box.y1); + + RRTransformCompute(0, 0, + sna->cursor.ref->bits->width, + sna->cursor.ref->bits->height, + crtc->rotation, &crtc->transform, + &cursor_to_fb, + &f_cursor_to_fb, + &f_fb_to_cursor); + } else + size = sna->cursor.size; + cursor = to_sna_crtc(crtc)->cursor; if (cursor && cursor->alloc < 4*size*size) cursor = NULL; @@ -4781,7 +4916,7 @@ } } - width = sna->cursor.ref->bits->width; + width = sna->cursor.ref->bits->width; height = sna->cursor.ref->bits->height; source = sna->cursor.ref->bits->source; mask = sna->cursor.ref->bits->mask; @@ -4789,7 +4924,7 @@ pitch = BitmapBytePad(width); image = cursor->image; - if (image == NULL) { + if (image == NULL || transformed) { image = sna->cursor.scratch; cursor->last_width = cursor->last_height = size; } @@ -4820,6 +4955,19 @@ mask += pitch; source += pitch; } + if (transformed) { + affine_blt(image, cursor->image, 32, + 0, 0, width, height, size * 4, + 0, 0, width, height, size * 4, + &f_cursor_to_fb); + image = cursor->image; + } + } else if (transformed) { + affine_blt(argb, cursor->image, 32, + 0, 0, width, height, width * 4, + 0, 0, width, height, size * 4, + &f_cursor_to_fb); + image = cursor->image; } else memcpy_blt(argb, image, 32, width * 4, size * 4, @@ -4866,6 +5014,7 @@ cursor->size = size; cursor->rotation = rotation; + cursor->transformed = transformed; cursor->serial = sna->cursor.serial; cursor->last_width = width; cursor->last_height = height; @@ -5199,17 +5348,6 @@ { } -static int __cursor_size(CursorPtr cursor) -{ - int i, size; - - i = MAX(cursor->bits->width, cursor->bits->height); - for (size = 64; size < i; size <<= 1) - ; - - return size; -} - static bool sna_cursor_preallocate(struct sna *sna) { @@ -5227,6 +5365,40 @@ return true; } +static bool +transformable_cursor(struct sna *sna, CursorPtr cursor) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn); + int i; + + for (i = 0; i < sna->mode.num_real_crtc; i++) { + xf86CrtcPtr crtc = config->crtc[i]; + const struct pixman_f_transform *t; + struct pixman_box16 box; + int size; + + if (!to_sna_crtc(crtc)->hwcursor) + return false; + + t = &crtc->f_crtc_to_framebuffer; + if (!sna->cursor.use_gtt || !sna->cursor.scratch) + return false; + + box.x1 = box.y1 = 0; + box.x2 = cursor->bits->width; + box.y2 = cursor->bits->height; + + if (!pixman_f_transform_bounds(t, &box)) + return false; + + size = __cursor_size(box.x2 - box.x1, box.y2 - box.y1); + if (size > sna->cursor.max_size) + return false; + } + + return true; +} + static Bool sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor) { @@ -5244,10 +5416,14 @@ sna->cursor.ref = NULL; } - sna->cursor.size = __cursor_size(cursor); + sna->cursor.size = + __cursor_size(cursor->bits->width, cursor->bits->height); if (sna->cursor.size > sna->cursor.max_size) return FALSE; + if (sna->mode.rr_active && !transformable_cursor(sna, cursor)) + return FALSE; + if (!sna_cursor_preallocate(sna)) return FALSE; @@ -5308,11 +5484,9 @@ DBG(("%s: cursor updates use_gtt?=%d\n", __FUNCTION__, sna->cursor.use_gtt)); - if (!sna->cursor.use_gtt) { - sna->cursor.scratch = malloc(sna->cursor.max_size * sna->cursor.max_size * 4); - if (!sna->cursor.scratch) - sna->cursor.max_size = 0; - } + sna->cursor.scratch = malloc(sna->cursor.max_size * sna->cursor.max_size * 4); + if (!sna->cursor.scratch && !sna->cursor.use_gtt) + sna->cursor.max_size = 0; sna->cursor.num_stash = -sna->mode.num_real_crtc; @@ -5973,8 +6147,8 @@ if (sna_output->num_modes == 0) continue; - width = sna_output->modes[0].hdisplay; - height= sna_output->modes[0].vdisplay; + width = sna_output->modes[0].hdisplay; + height = sna_output->modes[0].vdisplay; DBG(("%s: panel '%s' is %dx%d\n", __FUNCTION__, output->name, width, height)); @@ -6292,9 +6466,26 @@ sna->mode.dirty = false; } +static void sna_randr_close(struct sna *sna) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn); + int n; + + /* The RR structs are freed early during CloseScreen as they + * are tracked as Resources. However, we may be tempted to + * access them during shutdown so decouple them now. + */ + for (n = 0; n < config->num_output; n++) + config->output[n]->randr_output = NULL; + + for (n = 0; n < config->num_crtc; n++) + config->crtc[n]->randr_crtc = NULL; +} + void sna_mode_close(struct sna *sna) { + sna_randr_close(sna); sna_mode_wakeup(sna); if (sna->flags & SNA_IS_HOSTED) @@ -6960,6 +7151,14 @@ __FUNCTION__, format->format, depth, draw->bitsPerPixel, bo->pitch, crtc->mode.HDisplay, crtc->mode.VDisplay)); + if (sx | sy) + RegionTranslate(region, sx, sy); + error = !sna_drawable_move_region_to_cpu(draw, region, MOVE_READ); + if (sx | sy) + RegionTranslate(region, -sx, -sy); + if (error) + return; + ptr = kgem_bo_map__gtt(&sna->kgem, bo); if (ptr == NULL) return; @@ -6982,6 +7181,29 @@ pixman_transform_init_translate(&T, sx << 16, sy << 16); pixman_transform_multiply(&T, &T, &crtc->crtc_to_framebuffer); if (!sna_transform_is_integer_translation(&T, &sx, &sy)) { +#define f2d(x) (((double)(x))/65536.) + DBG(("%s: transform=[[%f %f %f], [%f %f %f], [%f %f %f]] (raw [[%x %x %x], [%x %x %x], [%x %x %x]])\n", + __FUNCTION__, + f2d(T.matrix[0][0]), + f2d(T.matrix[0][1]), + f2d(T.matrix[0][2]), + f2d(T.matrix[1][0]), + f2d(T.matrix[1][1]), + f2d(T.matrix[1][2]), + f2d(T.matrix[2][0]), + f2d(T.matrix[2][1]), + f2d(T.matrix[2][2]), + T.matrix[0][0], + T.matrix[0][1], + T.matrix[0][2], + T.matrix[1][0], + T.matrix[1][1], + T.matrix[1][2], + T.matrix[2][0], + T.matrix[2][1], + T.matrix[2][2])); +#undef f2d + error = SetPictureTransform(src, &T); if (error) goto free_src; diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/sna_dri2.c xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/sna_dri2.c --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/sna_dri2.c 2015-03-04 15:55:22.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/sna_dri2.c 2015-03-18 16:54:47.000000000 +0000 @@ -121,6 +121,7 @@ xf86CrtcPtr crtc; int pipe; bool queued; + bool sync; /* for swaps & flips only */ DRI2SwapEventPtr event_complete; @@ -140,13 +141,13 @@ #if DRI2INFOREC_VERSION < 10 #undef USE_ASYNC_SWAP -#define USE_ASYNC_SWAP 0 #endif #if USE_ASYNC_SWAP #define KEEPALIVE 4 /* wait ~50ms before discarding swap caches */ #define APPLY_DAMAGE 0 #else +#define USE_ASYNC_SWAP 0 #define KEEPALIVE 1 #define APPLY_DAMAGE 1 #endif @@ -233,7 +234,7 @@ } flags = 0; - if (USE_ASYNC_SWAP) { + if (USE_ASYNC_SWAP && back->flags) { BoxRec box; box.x1 = 0; @@ -242,7 +243,6 @@ box.y2 = draw->height; DBG(("%s: filling new buffer with old back\n", __FUNCTION__)); - assert(back->flags); if (sna->render.copy_boxes(sna, GXcopy, draw, get_private(back)->bo, 0, 0, draw, bo, 0, 0, @@ -1186,6 +1186,15 @@ return bo; } +inline static void +__sna_dri2_copy_event(struct sna_dri2_event *info, unsigned flags) +{ + info->bo = __sna_dri2_copy_region(info->sna, info->draw, NULL, + info->back, info->front, + flags); + info->front->flags = info->back->flags; +} + static void sna_dri2_copy_region(DrawablePtr draw, RegionPtr region, @@ -2157,9 +2166,7 @@ sna_dri2_xchg_crtc(chain->sna, chain->draw, chain->crtc, chain->front, chain->back); } else { assert(chain->queued); - chain->bo = __sna_dri2_copy_region(chain->sna, chain->draw, NULL, - chain->back, chain->front, - DRI2_SYNC); + __sna_dri2_copy_event(chain, 0); } case SWAP: break; @@ -2173,15 +2180,13 @@ DRM_VBLANK_EVENT; vbl.request.sequence = 1; vbl.request.signal = (uintptr_t)chain; - if (sna_wait_vblank(chain->sna, &vbl, chain->pipe)) { + if ((chain->type == SWAP_THROTTLE && + !swap_limit(chain->draw, 2 + !chain->sync) && + !chain->sync) || + sna_wait_vblank(chain->sna, &vbl, chain->pipe)) { DBG(("%s: vblank wait failed, unblocking client\n", __FUNCTION__)); frame_swap_complete(chain, DRI2_BLIT_COMPLETE); sna_dri2_event_free(chain); - } else { - if (chain->type == SWAP_THROTTLE && !swap_limit(chain->draw, 2)) { - DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__)); - frame_swap_complete(chain, DRI2_BLIT_COMPLETE); - } } } @@ -2267,9 +2272,7 @@ info->type = SWAP_WAIT; } else { assert(info->queued); - info->bo = __sna_dri2_copy_region(sna, draw, NULL, - info->back, info->front, - DRI2_SYNC); + __sna_dri2_copy_event(info, DRI2_SYNC); info->type = SWAP_WAIT; } @@ -2335,57 +2338,65 @@ DBG(("%s complete\n", __FUNCTION__)); } -static bool +static void sna_dri2_immediate_blit(struct sna *sna, struct sna_dri2_event *info, - bool sync, bool event) + bool sync) { DrawablePtr draw = info->draw; - bool ret = false; + struct sna_dri2_event *chain = dri2_chain(draw); if (sna->flags & SNA_NO_WAIT) sync = false; - DBG(("%s: emitting immediate blit, throttling client, synced? %d, chained? %d, send-event? %d\n", - __FUNCTION__, sync, dri2_chain(draw) != info, - event)); + DBG(("%s: emitting immediate blit, throttling client, synced? %d, chained? %d\n", + __FUNCTION__, sync, chain != info)); info->type = SWAP_THROTTLE; - if (!sync || dri2_chain(draw) == info) { - DBG(("%s: no pending blit, starting chain\n", - __FUNCTION__)); + info->sync = sync; + if (chain == info) { + union drm_wait_vblank vbl; + + DBG(("%s: no pending blit, starting chain\n", __FUNCTION__)); info->queued = true; - info->bo = __sna_dri2_copy_region(sna, draw, NULL, - info->back, - info->front, - sync); - if (event) { - if (sync) { - union drm_wait_vblank vbl; + __sna_dri2_copy_event(info, sync); - VG_CLEAR(vbl); - vbl.request.type = - DRM_VBLANK_RELATIVE | - DRM_VBLANK_EVENT; - vbl.request.sequence = 1; - vbl.request.signal = (uintptr_t)info; - ret = !sna_wait_vblank(sna, &vbl, info->pipe); - if (ret) - event = !swap_limit(draw, 2); - } - if (event) { - DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__)); - frame_swap_complete(info, DRI2_BLIT_COMPLETE); - } + VG_CLEAR(vbl); + vbl.request.type = + DRM_VBLANK_RELATIVE | + DRM_VBLANK_EVENT; + vbl.request.sequence = 1; + vbl.request.signal = (uintptr_t)info; + if ((!swap_limit(draw, 2 + !sync) && !sync) || + sna_wait_vblank(sna, &vbl, info->pipe)) { + DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__)); + frame_swap_complete(info, DRI2_BLIT_COMPLETE); + sna_dri2_event_free(info); } - } else { - DBG(("%s: pending blit, chained\n", __FUNCTION__)); - ret = true; + return; + } + + if (chain->chain != info && chain->chain->type == SWAP_THROTTLE) { + struct sna_dri2_event *tmp = chain->chain; + + assert(!tmp->queued); + + assert(info->chain == NULL); + info->chain = tmp->chain; + if (info->chain == info) + info->chain = NULL; + chain->chain = info; + tmp->chain = NULL; + + DBG(("%s: swap elision, unblocking client\n", __FUNCTION__)); + frame_swap_complete(tmp, DRI2_BLIT_COMPLETE); + + tmp->draw = NULL; + sna_dri2_event_free(tmp); } - DBG(("%s: continue? %d\n", __FUNCTION__, ret)); - return ret; + DBG(("%s: pending blit, chained\n", __FUNCTION__)); } static bool @@ -2454,9 +2465,7 @@ DBG(("%s: performing chained flip\n", __FUNCTION__)); } else { DBG(("%s: emitting chained vsync'ed blit\n", __FUNCTION__)); - chain->bo = __sna_dri2_copy_region(sna, chain->draw, NULL, - chain->back, chain->front, - DRI2_SYNC); + __sna_dri2_copy_event(chain, DRI2_SYNC); if (xorg_can_triple_buffer()) { union drm_wait_vblank vbl; @@ -2524,8 +2533,13 @@ } } else if (!sna_dri2_flip_continue(flip)) { DBG(("%s: no longer able to flip\n", __FUNCTION__)); - if (flip->draw == NULL || !sna_dri2_immediate_blit(sna, flip, false, flip->flip_continue == FLIP_COMPLETE)) - sna_dri2_event_free(flip); + if (flip->draw != NULL) + __sna_dri2_copy_event(flip, 0); + if (flip->flip_continue == FLIP_COMPLETE) { + DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__)); + frame_swap_complete(flip, DRI2_BLIT_COMPLETE); + } + sna_dri2_event_free(flip); } break; @@ -3066,8 +3080,7 @@ if (immediate) { bool sync = current_msc < *target_msc; - if (!sna_dri2_immediate_blit(sna, info, sync, true)) - sna_dri2_event_free(info); + sna_dri2_immediate_blit(sna, info, sync); *target_msc = current_msc + sync; return TRUE; } @@ -3083,9 +3096,7 @@ if (*target_msc <= current_msc + 1) { DBG(("%s: performing blit before queueing\n", __FUNCTION__)); assert(info->queued); - info->bo = __sna_dri2_copy_region(sna, draw, NULL, - back, front, - DRI2_SYNC); + __sna_dri2_copy_event(info, DRI2_SYNC); info->type = SWAP_WAIT; vbl.request.type = @@ -3111,6 +3122,7 @@ sna_dri2_xchg(draw, front, back); } else { __sna_dri2_copy_region(sna, draw, NULL, back, front, 0); + front->flags = back->flags; type = DRI2_BLIT_COMPLETE; } skip: diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/sna_driver.c xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/sna_driver.c --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/sna_driver.c 2015-03-04 15:55:22.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/sna_driver.c 2015-03-18 16:54:47.000000000 +0000 @@ -708,7 +708,7 @@ sna->BlockHandler(BLOCKHANDLER_ARGS); if (*tv == NULL || ((*tv)->tv_usec | (*tv)->tv_sec) || has_shadow(sna)) - sna_accel_block_handler(sna, tv); + sna_accel_block(sna, tv); } static void @@ -730,8 +730,6 @@ sna->WakeupHandler(WAKEUPHANDLER_ARGS); - sna_accel_wakeup_handler(sna); - if (FD_ISSET(sna->kgem.fd, (fd_set*)read_mask)) { sna_mode_wakeup(sna); /* Clear the flag so that subsequent ZaphodHeads don't block */ @@ -772,7 +770,6 @@ if (scrn->vtSema) { sna_mode_discover(sna); sna_mode_check(sna); - RRGetInfo(xf86ScrnToScreen(scrn), TRUE); } else sna->flags |= SNA_REPROBE; } @@ -1208,12 +1205,11 @@ return FALSE; if (sna->flags & SNA_REPROBE) { - DBG(("%s: reporting deferred hotplug event\n", - __FUNCTION__)); + DBG(("%s: reporting deferred hotplug event\n", __FUNCTION__)); sna_mode_discover(sna); - RRGetInfo(xf86ScrnToScreen(scrn), TRUE); sna->flags &= ~SNA_REPROBE; } + sna_mode_check(sna); if (!sna_set_desired_mode(sna)) { intel_put_master(sna->dev); diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/sna.h xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/sna.h --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/sna.h 2015-03-04 15:55:22.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/sna.h 2015-03-18 16:54:47.000000000 +0000 @@ -1013,8 +1013,7 @@ bool sna_accel_init(ScreenPtr sreen, struct sna *sna); void sna_accel_create(struct sna *sna); -void sna_accel_block_handler(struct sna *sna, struct timeval **tv); -void sna_accel_wakeup_handler(struct sna *sna); +void sna_accel_block(struct sna *sna, struct timeval **tv); void sna_accel_watch_flush(struct sna *sna, int enable); void sna_accel_flush(struct sna *sna); void sna_accel_enter(struct sna *sna); @@ -1142,6 +1141,16 @@ uint16_t width, uint16_t height); void +affine_blt(const void *src, void *dst, int bpp, + int16_t src_x, int16_t src_y, + int16_t src_width, int16_t src_height, + int32_t src_stride, + int16_t dst_x, int16_t dst_y, + uint16_t dst_width, uint16_t dst_height, + int32_t dst_stride, + const struct pixman_f_transform *t); + +void memmove_box(const void *src, void *dst, int bpp, int32_t stride, const BoxRec *box, diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/xassert.h xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/xassert.h --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/src/sna/xassert.h 2015-01-14 14:51:59.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/src/sna/xassert.h 2015-03-18 16:54:47.000000000 +0000 @@ -43,6 +43,17 @@ xorg_backtrace(); \ FatalError("%s:%d assertion '%s' failed\n", __func__, __LINE__, #E); \ } while (0) + +#define warn_unless(E) do if (unlikely(!(E))) { \ + static int __warn_once__; \ + if (!__warn_once__) { \ + xorg_backtrace(); \ + ErrorF("%s:%d assertion '%s' failed\n", __func__, __LINE__, #E); \ + __warn_once__ = 1; \ + } \ +} while (0) +#else +#define warn_unless(E) #endif #endif /* __XASSERT_H__ */ diff -Nru xserver-xorg-video-intel-2.99.917+git20150304.88e61542/tools/cursor.c xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/tools/cursor.c --- xserver-xorg-video-intel-2.99.917+git20150304.88e61542/tools/cursor.c 2015-03-04 15:55:22.000000000 +0000 +++ xserver-xorg-video-intel-2.99.917+git20150318.bacaf7f1/tools/cursor.c 2015-03-18 16:54:47.000000000 +0000 @@ -29,8 +29,9 @@ #include #include -#include #include +#include +#include #include int main(int argc, char **argv)