mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2026-02-13 08:10:30 +01:00
The width parameter is used to disable the blit fast-path (memcpy) when
source and destination rows overlap in memory. This check was added in [0].
Unfortunately, the calculation to determine if source and destination
lines overlapped was incorrect:
(1) it converts width from pixels to bytes, but width is actually in
bits, not pixels.
(2) it adds this byte offset to dst/srcLine, which implicitly converts
the offset from bytes to sizeof(FbBits).
Fix both of these by converting addresses to byte pointers and width
to bytes and doing comparisons on the resulting byte address.
For example:
A 32-bpp 1366 pixel-wide row will have
width = 1366 * 32 = 43712 bits
bpp = 32
(bpp >> 3) = 4
width * (bpp >> 3) = 174848 FbBits
(FbBits *)width => 699392 bytes
So, "careful" was true if the destination line was within 699392 bytes,
instead of just within its 1366 * 4 = 5464 byte row.
This bug causes us to take the slow path for large non-overlapping rows
that are "close" in memory. As a data point, XGetImage(1366x768) on my
ARM chromebook was taking ~140 ms, but with this fixed, it now takes
about 60 ms.
XGetImage() -> exaGetImage() -> fbGetImage -> fbBlt()
[0] commit
|
||
|---|---|---|
| .. | ||
| fb.h | ||
| fb24_32.c | ||
| fb24_32.h | ||
| fballpriv.c | ||
| fbarc.c | ||
| fbbits.c | ||
| fbbits.h | ||
| fbblt.c | ||
| fbbltone.c | ||
| fbcmap_mi.c | ||
| fbcopy.c | ||
| fbfill.c | ||
| fbfillrect.c | ||
| fbfillsp.c | ||
| fbgc.c | ||
| fbgetsp.c | ||
| fbglyph.c | ||
| fbimage.c | ||
| fbline.c | ||
| fboverlay.c | ||
| fboverlay.h | ||
| fbpict.c | ||
| fbpict.h | ||
| fbpixmap.c | ||
| fbpoint.c | ||
| fbpush.c | ||
| fbrop.h | ||
| fbscreen.c | ||
| fbseg.c | ||
| fbsetsp.c | ||
| fbsolid.c | ||
| fbstipple.c | ||
| fbtile.c | ||
| fbtrap.c | ||
| fbutil.c | ||
| fbwindow.c | ||
| Makefile.am | ||
| wfbrename.h | ||