summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Scott <barry.scott@onelan.co.uk>2009-06-23 14:14:50 +0100
committerIan Romanick <ian.d.romanick@intel.com>2009-07-02 13:36:56 -0700
commit74227141923a2f5049592219ab80e8733062a5d9 (patch)
treea344f9492f0ef61ad5fd6660f4e46cc67d5c7e44
parentc1755599db1d9a20954b84ccc07afd892bb6ac9e (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.c22
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++) {