diff options
author | Barry Scott <barry.scott@onelan.co.uk> | 2009-06-23 14:14:50 +0100 |
---|---|---|
committer | Ian Romanick <ian.d.romanick@intel.com> | 2009-07-02 13:36:56 -0700 |
commit | 74227141923a2f5049592219ab80e8733062a5d9 (patch) | |
tree | a344f9492f0ef61ad5fd6660f4e46cc67d5c7e44 | |
parent | c1755599db1d9a20954b84ccc07afd892bb6ac9e (diff) |
Fix segv for clipped movie window
When playing a movie that is clipped on its left and right edges the Xorg
server will SEGV sometimes. This is because the intel driver ignores the
clipping info when it copies the planes out of the XV data.
The check for the optimised copy was wrong to ignore the width required.
Which leads to too much data being copied by the memcpy. It the source buffer
happens to end exactly on a page boundary the server will SEGV.
As we reviewed the code we checked the calculation of src1, src2 and src3.
The patch includes additional comments to make it clear what the elements of
the calculation are.
This bug exists in git head and we also see it in 2.4.1.
Barry
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
-rw-r--r-- | src/i830_video.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/src/i830_video.c b/src/i830_video.c index c295159a..573d6812 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -1399,7 +1399,8 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, switch (pPriv->rotation) { case RR_Rotate_0: - if (srcPitch == dstPitch2) + /* optimise for the case of no clipping */ + if (srcPitch == dstPitch2 && srcPitch == w) memcpy (dst1, src1, srcPitch * h); else for (i = 0; i < h; i++) { @@ -1438,7 +1439,11 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, } /* Copy V data for YV12, or U data for I420 */ - src2 = buf + (srcH * srcPitch) + ((top * srcPitch) >> 2) + (left >> 1); + src2 = buf + /* start of YUV data */ + (srcH * srcPitch) + /* move over Luma plane */ + ((top * srcPitch) >> 2) + /* move down from by top lines */ + (left >> 1); /* move left by left pixels */ + #if 0 ErrorF("src2 is %p, offset is %ld\n", src2, (unsigned long)src2 - (unsigned long)buf); @@ -1457,7 +1462,8 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, switch (pPriv->rotation) { case RR_Rotate_0: - if (srcPitch2 == dstPitch) + /* optimise for the case of no clipping */ + if (srcPitch2 == dstPitch && srcPitch2 == (w/2)) memcpy (dst2, src2, h/2 * srcPitch2); else for (i = 0; i < h / 2; i++) { @@ -1496,8 +1502,11 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, } /* Copy U data for YV12, or V data for I420 */ - src3 = buf + (srcH * srcPitch) + ((srcH >> 1) * srcPitch2) + - ((top * srcPitch) >> 2) + (left >> 1); + src3 = buf + /* start of YUV data */ + (srcH * srcPitch) + /* move over Luma plane */ + ((srcH >> 1) * srcPitch2) + /* move over Chroma plane */ + ((top * srcPitch) >> 2) + /* move down from by top lines */ + (left >> 1); /* move left by left pixels */ #if 0 ErrorF("src3 is %p, offset is %ld\n", src3, (unsigned long)src3 - (unsigned long)buf); @@ -1516,7 +1525,8 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, switch (pPriv->rotation) { case RR_Rotate_0: - if (srcPitch2 == dstPitch) + /* optimise for the case of no clipping */ + if (srcPitch2 == dstPitch && srcPitch2 == (w/2)) memcpy (dst3, src3, srcPitch2 * h/2); else for (i = 0; i < h / 2; i++) { |