tdevdraw: fix for OS X 10.8 (Mountain Lion) - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit ad4025bd76adf60caf9f3bcaaa9b2cc72dfe0dbc
 (DIR) parent 4ed8efea38afb72dfb0028a4470698563a4176e0
 (HTM) Author: Rob Kroeger <robkroeger@gmail.com>
       Date:   Tue, 31 Jul 2012 11:24:44 -0400
       
       devdraw: fix for OS X 10.8 (Mountain Lion)
       
       In MacOS 10.8, the NSBitmapImageRep class appears to cache the specified
       image data at the time of construction. As a result updates to the
       backing memimage object do not get pushed to the screen in flushimg.
       
       This patch creates the NSBitmapImageRep object over again for each
       flushimg which would appear to fix the problem.
       
       R=rsc
       CC=plan9port.codebot
       http://codereview.appspot.com/6443063
       
       Diffstat:
         M src/cmd/devdraw/cocoa-screen.m      |      71 +++++++++++++++++--------------
       
       1 file changed, 40 insertions(+), 31 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/devdraw/cocoa-screen.m b/src/cmd/devdraw/cocoa-screen.m
       t@@ -95,10 +95,10 @@ struct
                int                        isofs;
                int                        isnfs;
                NSView                *content;
       -        NSBitmapImageRep        *img;
                int                        needimg;
                int                        deferflush;
                NSCursor                *cursor;
       +        Memimage *memimage;
        } win;
        
        struct
       t@@ -348,7 +348,6 @@ makewin(char *s)
        static Memimage*
        initimg(void)
        {
       -        Memimage *i;
                NSSize size;
                Rectangle r;
        
       t@@ -356,32 +355,19 @@ initimg(void)
                LOG(@"initimg %.0f %.0f", size.width, size.height);
        
                r = Rect(0, 0, size.width, size.height);
       -        i = allocmemimage(r, XBGR32);
       -        if(i == nil)
       +        win.memimage = allocmemimage(r, XBGR32);
       +        if(win.memimage == nil)
                        panic("allocmemimage: %r");
       -        if(i->data == nil)
       +        if(win.memimage->data == nil)
                        panic("i->data == nil");
        
       -        win.img = [[NSBitmapImageRep alloc]
       -                initWithBitmapDataPlanes:&i->data->bdata
       -                pixelsWide:Dx(r)
       -                pixelsHigh:Dy(r)
       -                bitsPerSample:8
       -                samplesPerPixel:3
       -                hasAlpha:NO
       -                isPlanar:NO
       -                colorSpaceName:NSDeviceRGBColorSpace
       -                bytesPerRow:bytesperline(r, 32)
       -                bitsPerPixel:32];
       -        return i;
       +        return win.memimage;
        }
        
        static void
        resizeimg()
        {
       -        [win.img release];
                _drawreplacescreenimage(initimg());
       -
                mouseresized = 1;
                sendmouse();
        }
       t@@ -441,7 +427,7 @@ _flushmemscreen(Rectangle r)
                                @"waiting image", nil]];
        }
        
       -static void drawimg(NSRect, uint);
       +static void drawimg(NSBitmapImageRep*, NSRect, uint);
        static void drawresizehandle(void);
        
        enum
       t@@ -456,12 +442,17 @@ static void
        flushimg(NSRect rect)
        {
                NSRect dr, r;
       +        NSBitmapImageRep *image;
       +        Rectangle rrect;
       +        NSSize size;
        
                if([win.content lockFocusIfCanDraw] == 0)
                        return;
        
                if(win.needimg){
       -                if(!NSEqualSizes(rect.size, [win.img size])){
       +          size.width = win.memimage->r.max.x - win.memimage->r.min.x;
       +          size.height = win.memimage->r.max.y - win.memimage->r.min.y;
       +                if(!NSEqualSizes(rect.size, size)){
                                LOG(@"flushimg reject %.0f %.0f",
                                        rect.size.width, rect.size.height);
                                [win.content unlockFocus];
       t@@ -473,6 +464,24 @@ flushimg(NSRect rect)
        
                LOG(@"flushimg ok %.0f %.0f", rect.size.width, rect.size.height);
        
       +
       +        size = [win.content bounds].size;
       +        LOG(@"initimg %.0f %.0f", size.width, size.height);
       +        rrect = Rect(0, 0, size.width, size.height);
       +
       +        // FIXME: It is possible that we could do a smaller pixel copy here.
       +        image = [[NSBitmapImageRep alloc]
       +                initWithBitmapDataPlanes:&win.memimage->data->bdata
       +                pixelsWide:Dx(rrect)
       +                pixelsHigh:Dy(rrect)
       +                bitsPerSample:8
       +                samplesPerPixel:3
       +                hasAlpha:NO
       +                isPlanar:NO
       +                colorSpaceName:NSDeviceRGBColorSpace
       +                bytesPerRow:bytesperline(rrect, 32)
       +                bitsPerPixel:32];
       +
                /*
                 * Unless we are inside "drawRect", we have to round
                 * the corners ourselves, if this is the custom.
       t@@ -484,25 +493,25 @@ flushimg(NSRect rect)
                r = [win.content bounds];
                r.size.height -= Cornersize;
                dr = NSIntersectionRect(r, rect);
       -        drawimg(dr, NSCompositeCopy);
       +        drawimg(image, dr, NSCompositeCopy);
        
                r.origin.y = r.size.height;
                r.size = NSMakeSize(Cornersize, Cornersize);
                dr = NSIntersectionRect(r, rect);
       -        drawimg(dr, NSCompositeSourceIn);
       +        drawimg(image, dr, NSCompositeSourceIn);
        
       -        r.origin.x = [win.img size].width - Cornersize;
       +        r.origin.x = size.width - Cornersize;
                dr = NSIntersectionRect(r, rect);
       -        drawimg(dr, NSCompositeSourceIn);
       +        drawimg(image, dr, NSCompositeSourceIn);
        
                r.size.width = r.origin.x - Cornersize;
                r.origin.x -= r.size.width;
                dr = NSIntersectionRect(r, rect);
       -        drawimg(dr, NSCompositeCopy);
       +        drawimg(image, dr, NSCompositeCopy);
        
                if(OSX_VERSION<100700 && win.isofs==0){
       -                r.origin.x = [win.img size].width - Handlesize;
       -                r.origin.y = [win.img size].height - Handlesize;
       +                r.origin.x = size.width - Handlesize;
       +                r.origin.y = size.height - Handlesize;
                        r.size = NSMakeSize(Handlesize, Handlesize);
                        if(NSIntersectsRect(r, rect))
                                drawresizehandle();
       t@@ -546,7 +555,7 @@ flushwin(void)
        }
        
        static void
       -drawimg(NSRect dr, uint op)
       +drawimg(NSBitmapImageRep* image, NSRect dr, uint op)
        {
                NSRect sr;
        
       t@@ -555,7 +564,7 @@ drawimg(NSRect dr, uint op)
        
                sr =  [win.content convertRect:dr fromView:nil];
        
       -        [win.img drawInRect:dr fromRect:sr
       +        [image drawInRect:dr fromRect:sr
                        operation:op fraction:1
                        respectFlipped:YES hints:nil];
        
       t@@ -570,7 +579,7 @@ drawresizehandle(void)
                Point c;
                int i,j;
        
       -        c = Pt([win.img size].width, [win.img size].height);
       +        c = Pt(win.memimage->r.max.x - win.memimage->r.min.x, win.memimage->r.max.y - win.memimage->r.min.y);
        
                [[WIN graphicsContext] setShouldAntialias:NO];