On 2026/06/14 9:04, Stefan Reinauer wrote:
Under zoom-to-fit, Cocoa redrew each dirty rect by cropping the
guest CGImage and drawing that crop into the dirty destination
rect. With non-integer scales, adjacent partial updates could sample
the source with different phase. Moving cursor updates then showed
one-line stretch/skew artifacts at the dirty band boundary.
This fix is fine, but I think it's unlikely that "adjacent partial
updates could sample the source with different phase". You'll observe
tearing even with integer scales if that is the case. This fix does not
deal with timing either.
My guess is that some fractions in rectList were rounded in
CGImageCreateWithImageInRect() or before reaching the function, and that
caused sampling one line more or less, causing stretch/skew artifacts.
Keep using AppKit's dirty-region clipping, but draw the full guest
image into the view bounds. Each partial update then uses the same
source transform while drawing remains limited to invalidated
regions.
Signed-off-by: Stefan Reinauer <[email protected]>
---
ui/cocoa.m | 25 +++++++------------------
1 file changed, 7 insertions(+), 18 deletions(-)
diff --git a/ui/cocoa.m b/ui/cocoa.m
index c5e639ab98..f294c20720 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -551,24 +551,13 @@ - (void) drawRect:(NSRect) rect
0, //interpolate
kCGRenderingIntentDefault //intent
);
- // selective drawing code (draws only dirty rectangles) (OS X >= 10.4)
- const NSRect *rectList;
- NSInteger rectCount;
- int i;
- CGImageRef clipImageRef;
- CGRect clipRect;
-
- [self getRectsBeingDrawn:&rectList count:&rectCount];
- for (i = 0; i < rectCount; i++) {
- clipRect = rectList[i];
- clipRect.origin.y = (float)h - (clipRect.origin.y +
clipRect.size.height);
- clipImageRef = CGImageCreateWithImageInRect(
- imageRef,
- clipRect
- );
- CGContextDrawImage (viewContextRef, cgrect(rectList[i]),
clipImageRef);
- CGImageRelease (clipImageRef);
- }
+ NSRect imageRect = NSMakeRect(0, 0, w, h);
+
+ /*
+ * AppKit already clips drawing to the dirty region. Draw the full
+ * guest image so scaled partial updates use a stable source transform.
+ */
+ CGContextDrawImage(viewContextRef, cgrect(imageRect), imageRef);
Please use CGRectMake().
Regards,
Akihiko Odaki
CGImageRelease (imageRef);
CGDataProviderRelease(dataProviderRef);
}