diff options
| author | Alan Third | 2020-02-01 21:17:29 +0000 |
|---|---|---|
| committer | Alan Third | 2020-02-13 18:26:20 +0000 |
| commit | 44298ea6aa006ed227e539b02279bd3fc11fd2a6 (patch) | |
| tree | c6381b6fecb47fa8751662535e42f1727fc7945b /src | |
| parent | a13d1f953980b516470d03ab23250760c581c05b (diff) | |
| download | emacs-44298ea6aa006ed227e539b02279bd3fc11fd2a6.tar.gz emacs-44298ea6aa006ed227e539b02279bd3fc11fd2a6.zip | |
Use CGImage instead of NSBitmapImageRep (bug#32932)
* src/nsterm.m (ns_update_end):
(ns_clear_frame): Remove forced draws.
(ns_draw_fringe_bitmap):
(ns_dumpglyphs_image): No longer need to invert images as the context
is already flipped.
([EmacsView updateFrameSize:]):
([EmacsView initFrameFromEmacs:]): Use new function.
([EmacsView createDrawingBuffer]): Replaces createDrawingBufferWithRect:.
([EmacsView focusOnDrawingBuffer]): Set CGImage context.
([EmacsView windowDidChangeBackingProperties:]): Use new function.
([EmacsView copyRect:to:]): Copy using CGImages.
([EmacsView wantsUpdateLayer]):
([EmacsView updateLayer]): New Functions.
([EmacsView drawRect:]): We no longer do anything special here for
Cocoa.
([EmacsView windowDidChangeBackingProperties:]): Fix indentation and
add NSTRACE.
Diffstat (limited to 'src')
| -rw-r--r-- | src/nsterm.h | 4 | ||||
| -rw-r--r-- | src/nsterm.m | 152 |
2 files changed, 90 insertions, 66 deletions
diff --git a/src/nsterm.h b/src/nsterm.h index 980ca534cfa..7c6197f1288 100644 --- a/src/nsterm.h +++ b/src/nsterm.h | |||
| @@ -418,7 +418,7 @@ typedef id instancetype; | |||
| 418 | NSWindow *nonfs_window; | 418 | NSWindow *nonfs_window; |
| 419 | BOOL fs_is_native; | 419 | BOOL fs_is_native; |
| 420 | #ifdef NS_IMPL_COCOA | 420 | #ifdef NS_IMPL_COCOA |
| 421 | NSBitmapImageRep *drawingBuffer; | 421 | CGContextRef drawingBuffer; |
| 422 | #endif | 422 | #endif |
| 423 | @public | 423 | @public |
| 424 | struct frame *emacsframe; | 424 | struct frame *emacsframe; |
| @@ -464,7 +464,7 @@ typedef id instancetype; | |||
| 464 | - (void)focusOnDrawingBuffer; | 464 | - (void)focusOnDrawingBuffer; |
| 465 | #endif | 465 | #endif |
| 466 | - (void)copyRect:(NSRect)srcRect to:(NSRect)dstRect; | 466 | - (void)copyRect:(NSRect)srcRect to:(NSRect)dstRect; |
| 467 | - (void)createDrawingBufferWithRect:(NSRect)rect; | 467 | - (void)createDrawingBuffer; |
| 468 | 468 | ||
| 469 | /* Non-notification versions of NSView methods. Used for direct calls. */ | 469 | /* Non-notification versions of NSView methods. Used for direct calls. */ |
| 470 | - (void)windowWillEnterFullScreen; | 470 | - (void)windowWillEnterFullScreen; |
diff --git a/src/nsterm.m b/src/nsterm.m index 9d427b9b38d..2cf6774a1f1 100644 --- a/src/nsterm.m +++ b/src/nsterm.m | |||
| @@ -1141,7 +1141,6 @@ ns_update_end (struct frame *f) | |||
| 1141 | 1141 | ||
| 1142 | #ifdef NS_IMPL_COCOA | 1142 | #ifdef NS_IMPL_COCOA |
| 1143 | [NSGraphicsContext setCurrentContext:nil]; | 1143 | [NSGraphicsContext setCurrentContext:nil]; |
| 1144 | [view display]; | ||
| 1145 | #else | 1144 | #else |
| 1146 | block_input (); | 1145 | block_input (); |
| 1147 | 1146 | ||
| @@ -2853,7 +2852,9 @@ ns_clear_frame (struct frame *f) | |||
| 2853 | ns_unfocus (f); | 2852 | ns_unfocus (f); |
| 2854 | 2853 | ||
| 2855 | /* as of 2006/11 or so this is now needed */ | 2854 | /* as of 2006/11 or so this is now needed */ |
| 2856 | ns_redraw_scroll_bars (f); | 2855 | /* FIXME: I don't see any reason for this and removing it makes no |
| 2856 | difference here. Do we need it for GNUstep? */ | ||
| 2857 | //ns_redraw_scroll_bars (f); | ||
| 2857 | unblock_input (); | 2858 | unblock_input (); |
| 2858 | } | 2859 | } |
| 2859 | 2860 | ||
| @@ -3169,18 +3170,6 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, | |||
| 3169 | 3170 | ||
| 3170 | NSTRACE_RECT ("fromRect", fromRect); | 3171 | NSTRACE_RECT ("fromRect", fromRect); |
| 3171 | 3172 | ||
| 3172 | /* Because we're drawing into an offscreen buffer which isn't | ||
| 3173 | flipped, the images come out upside down. To work around it | ||
| 3174 | we need to do some fancy transforms. */ | ||
| 3175 | { | ||
| 3176 | NSAffineTransform *transform = [NSAffineTransform transform]; | ||
| 3177 | [transform translateXBy:0 yBy:NSMaxY(imageRect)]; | ||
| 3178 | [transform scaleXBy:1 yBy:-1]; | ||
| 3179 | [transform concat]; | ||
| 3180 | |||
| 3181 | imageRect.origin.y = 0; | ||
| 3182 | } | ||
| 3183 | |||
| 3184 | [img drawInRect: imageRect | 3173 | [img drawInRect: imageRect |
| 3185 | fromRect: fromRect | 3174 | fromRect: fromRect |
| 3186 | operation: NSCompositingOperationSourceOver | 3175 | operation: NSCompositingOperationSourceOver |
| @@ -3938,11 +3927,6 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r) | |||
| 3938 | 3927 | ||
| 3939 | NSAffineTransform *doTransform = [NSAffineTransform transform]; | 3928 | NSAffineTransform *doTransform = [NSAffineTransform transform]; |
| 3940 | 3929 | ||
| 3941 | /* We have to flip the image around the X axis as the offscreen | ||
| 3942 | bitmap we're drawing to is flipped. */ | ||
| 3943 | [doTransform scaleXBy:1 yBy:-1]; | ||
| 3944 | [doTransform translateXBy:0 yBy:-[img size].height]; | ||
| 3945 | |||
| 3946 | /* ImageMagick images don't have transforms. */ | 3930 | /* ImageMagick images don't have transforms. */ |
| 3947 | if (img->transform) | 3931 | if (img->transform) |
| 3948 | [doTransform appendTransform:img->transform]; | 3932 | [doTransform appendTransform:img->transform]; |
| @@ -7104,7 +7088,7 @@ not_in_argv (NSString *arg) | |||
| 7104 | from non-native fullscreen, in other circumstances it appears | 7088 | from non-native fullscreen, in other circumstances it appears |
| 7105 | to be a noop. (bug#28872) */ | 7089 | to be a noop. (bug#28872) */ |
| 7106 | wr = NSMakeRect (0, 0, neww, newh); | 7090 | wr = NSMakeRect (0, 0, neww, newh); |
| 7107 | [self createDrawingBufferWithRect:wr]; | 7091 | [self createDrawingBuffer]; |
| 7108 | [view setFrame: wr]; | 7092 | [view setFrame: wr]; |
| 7109 | 7093 | ||
| 7110 | // To do: consider using [NSNotificationCenter postNotificationName:]. | 7094 | // To do: consider using [NSNotificationCenter postNotificationName:]. |
| @@ -7444,7 +7428,7 @@ not_in_argv (NSString *arg) | |||
| 7444 | maximizing_resize = NO; | 7428 | maximizing_resize = NO; |
| 7445 | #endif | 7429 | #endif |
| 7446 | 7430 | ||
| 7447 | [self createDrawingBufferWithRect:r]; | 7431 | [self createDrawingBuffer]; |
| 7448 | 7432 | ||
| 7449 | win = [[EmacsWindow alloc] | 7433 | win = [[EmacsWindow alloc] |
| 7450 | initWithContentRect: r | 7434 | initWithContentRect: r |
| @@ -8229,52 +8213,65 @@ not_in_argv (NSString *arg) | |||
| 8229 | } | 8213 | } |
| 8230 | 8214 | ||
| 8231 | 8215 | ||
| 8232 | - (void)createDrawingBufferWithRect:(NSRect)rect | 8216 | #ifdef NS_IMPL_COCOA |
| 8233 | /* Create and store a new NSBitmapImageRep for Emacs to draw | 8217 | - (void)createDrawingBuffer |
| 8234 | into. | 8218 | /* Create and store a new CGGraphicsContext for Emacs to draw into. |
| 8235 | 8219 | ||
| 8236 | Drawing to an offscreen bitmap doesn't work in GNUstep as there's | 8220 | We can't do this in GNUstep as there's no equivalent, so under |
| 8237 | a bug in graphicsContextWithBitmapImageRep | 8221 | GNUstep we retain the old method of drawing direct to the |
| 8238 | (https://savannah.gnu.org/bugs/?38405). So under GNUstep we | 8222 | EmacsView. */ |
| 8239 | retain the old method of drawing direct to the EmacsView. */ | ||
| 8240 | { | 8223 | { |
| 8241 | #ifdef NS_IMPL_COCOA | 8224 | NSTRACE ("EmacsView createDrawingBuffer]"); |
| 8225 | |||
| 8226 | NSGraphicsContext *screen; | ||
| 8227 | CGColorSpaceRef colorSpace = [[[self window] colorSpace] CGColorSpace]; | ||
| 8228 | CGFloat scale = [[self window] backingScaleFactor]; | ||
| 8229 | NSRect frame = [self frame]; | ||
| 8230 | |||
| 8242 | if (drawingBuffer != nil) | 8231 | if (drawingBuffer != nil) |
| 8243 | [drawingBuffer release]; | 8232 | CGContextRelease (drawingBuffer); |
| 8244 | 8233 | ||
| 8245 | drawingBuffer = [[self bitmapImageRepForCachingDisplayInRect:rect] retain]; | 8234 | drawingBuffer = CGBitmapContextCreate (nil, NSWidth (frame) * scale, NSHeight (frame) * scale, |
| 8246 | #endif | 8235 | 8, 0, colorSpace, |
| 8236 | kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); | ||
| 8237 | |||
| 8238 | /* This fixes the scale to match the backing scale factor, and flips the image. */ | ||
| 8239 | CGContextTranslateCTM(drawingBuffer, 0, NSHeight (frame) * scale); | ||
| 8240 | CGContextScaleCTM(drawingBuffer, scale, -scale); | ||
| 8247 | } | 8241 | } |
| 8248 | 8242 | ||
| 8249 | 8243 | ||
| 8250 | #ifdef NS_IMPL_COCOA | ||
| 8251 | - (void)focusOnDrawingBuffer | 8244 | - (void)focusOnDrawingBuffer |
| 8252 | { | 8245 | { |
| 8253 | /* Creating the graphics context each time is very slow, but it | 8246 | NSTRACE ("EmacsView focusOnDrawingBuffer]"); |
| 8254 | doesn't seem possible to cache and reuse it. */ | 8247 | |
| 8255 | [NSGraphicsContext | 8248 | NSGraphicsContext *buf = |
| 8256 | setCurrentContext: | 8249 | [NSGraphicsContext |
| 8257 | [NSGraphicsContext graphicsContextWithBitmapImageRep:drawingBuffer]]; | 8250 | graphicsContextWithCGContext:drawingBuffer flipped:YES]; |
| 8251 | |||
| 8252 | [NSGraphicsContext setCurrentContext:buf]; | ||
| 8258 | } | 8253 | } |
| 8259 | 8254 | ||
| 8260 | 8255 | ||
| 8261 | - (void)windowDidChangeBackingProperties:(NSNotification *)notification | 8256 | - (void)windowDidChangeBackingProperties:(NSNotification *)notification |
| 8262 | /* Update the drawing buffer when the backing scale factor changes. */ | 8257 | /* Update the drawing buffer when the backing scale factor changes. */ |
| 8263 | { | 8258 | { |
| 8264 | CGFloat old = [[[notification userInfo] | 8259 | NSTRACE ("EmacsView windowDidChangeBackingProperties:]"); |
| 8260 | |||
| 8261 | CGFloat old = [[[notification userInfo] | ||
| 8265 | objectForKey:@"NSBackingPropertyOldScaleFactorKey"] | 8262 | objectForKey:@"NSBackingPropertyOldScaleFactorKey"] |
| 8266 | doubleValue]; | 8263 | doubleValue]; |
| 8267 | CGFloat new = [[self window] backingScaleFactor]; | 8264 | CGFloat new = [[self window] backingScaleFactor]; |
| 8268 | 8265 | ||
| 8269 | if (old != new) | 8266 | if (old != new) |
| 8270 | { | 8267 | { |
| 8271 | NSRect frame = [self frame]; | 8268 | NSRect frame = [self frame]; |
| 8272 | [self createDrawingBufferWithRect:frame]; | 8269 | [self createDrawingBuffer]; |
| 8273 | ns_clear_frame (emacsframe); | 8270 | ns_clear_frame (emacsframe); |
| 8274 | expose_frame (emacsframe, 0, 0, NSWidth (frame), NSHeight (frame)); | 8271 | expose_frame (emacsframe, 0, 0, NSWidth (frame), NSHeight (frame)); |
| 8275 | } | 8272 | } |
| 8276 | } | 8273 | } |
| 8277 | #endif | 8274 | #endif /* NS_IMPL_COCOA */ |
| 8278 | 8275 | ||
| 8279 | 8276 | ||
| 8280 | - (void)copyRect:(NSRect)srcRect to:(NSRect)dstRect | 8277 | - (void)copyRect:(NSRect)srcRect to:(NSRect)dstRect |
| @@ -8284,13 +8281,31 @@ not_in_argv (NSString *arg) | |||
| 8284 | NSTRACE_RECT ("Destination", dstRect); | 8281 | NSTRACE_RECT ("Destination", dstRect); |
| 8285 | 8282 | ||
| 8286 | #ifdef NS_IMPL_COCOA | 8283 | #ifdef NS_IMPL_COCOA |
| 8287 | [drawingBuffer drawInRect:dstRect | 8284 | CGImageRef copy; |
| 8288 | fromRect:srcRect | 8285 | NSRect frame = [self frame]; |
| 8289 | operation:NSCompositingOperationCopy | 8286 | NSAffineTransform *setOrigin = [NSAffineTransform transform]; |
| 8290 | fraction:1.0 | 8287 | |
| 8291 | respectFlipped:NO | 8288 | [[NSGraphicsContext currentContext] saveGraphicsState]; |
| 8292 | hints:nil]; | 8289 | |
| 8290 | /* Set the clipping before messing with the buffer's | ||
| 8291 | orientation. */ | ||
| 8292 | NSRectClip (dstRect); | ||
| 8293 | |||
| 8294 | /* Unflip the buffer as the copied image will be unflipped, and | ||
| 8295 | offset the top left so when we draw back into the buffer the | ||
| 8296 | correct part of the image is drawn. */ | ||
| 8297 | CGContextScaleCTM(drawingBuffer, 1, -1); | ||
| 8298 | CGContextTranslateCTM(drawingBuffer, 0, -NSHeight (frame) | ||
| 8299 | - (NSMinY (dstRect) - NSMinY (srcRect))); | ||
| 8300 | |||
| 8301 | /* Take a copy of the buffer and then draw it back to the buffer, | ||
| 8302 | limited by the clipping rectangle. */ | ||
| 8303 | copy = CGBitmapContextCreateImage (drawingBuffer); | ||
| 8304 | CGContextDrawImage (drawingBuffer, frame, copy); | ||
| 8305 | |||
| 8306 | CGImageRelease (copy); | ||
| 8293 | 8307 | ||
| 8308 | [[NSGraphicsContext currentContext] restoreGraphicsState]; | ||
| 8294 | [self setNeedsDisplayInRect:dstRect]; | 8309 | [self setNeedsDisplayInRect:dstRect]; |
| 8295 | #else | 8310 | #else |
| 8296 | hide_bell(); // Ensure the bell image isn't scrolled. | 8311 | hide_bell(); // Ensure the bell image isn't scrolled. |
| @@ -8304,6 +8319,24 @@ not_in_argv (NSString *arg) | |||
| 8304 | } | 8319 | } |
| 8305 | 8320 | ||
| 8306 | 8321 | ||
| 8322 | #ifdef NS_IMPL_COCOA | ||
| 8323 | - (BOOL)wantsUpdateLayer | ||
| 8324 | { | ||
| 8325 | return YES; | ||
| 8326 | } | ||
| 8327 | |||
| 8328 | |||
| 8329 | - (void)updateLayer | ||
| 8330 | { | ||
| 8331 | NSTRACE ("EmacsView updateLayer]"); | ||
| 8332 | |||
| 8333 | CGImageRef contentsImage = CGBitmapContextCreateImage(drawingBuffer); | ||
| 8334 | [[self layer] setContents:(id)contentsImage]; | ||
| 8335 | CGImageRelease(contentsImage); | ||
| 8336 | } | ||
| 8337 | #endif | ||
| 8338 | |||
| 8339 | |||
| 8307 | - (void)drawRect: (NSRect)rect | 8340 | - (void)drawRect: (NSRect)rect |
| 8308 | { | 8341 | { |
| 8309 | NSTRACE ("[EmacsView drawRect:" NSTRACE_FMT_RECT "]", | 8342 | NSTRACE ("[EmacsView drawRect:" NSTRACE_FMT_RECT "]", |
| @@ -8312,14 +8345,6 @@ not_in_argv (NSString *arg) | |||
| 8312 | if (!emacsframe || !emacsframe->output_data.ns) | 8345 | if (!emacsframe || !emacsframe->output_data.ns) |
| 8313 | return; | 8346 | return; |
| 8314 | 8347 | ||
| 8315 | #ifdef NS_IMPL_COCOA | ||
| 8316 | [drawingBuffer drawInRect:rect | ||
| 8317 | fromRect:rect | ||
| 8318 | operation:NSCompositingOperationSourceOver | ||
| 8319 | fraction:1 | ||
| 8320 | respectFlipped:NO | ||
| 8321 | hints:nil]; | ||
| 8322 | #else | ||
| 8323 | int x = NSMinX (rect), y = NSMinY (rect); | 8348 | int x = NSMinX (rect), y = NSMinY (rect); |
| 8324 | int width = NSWidth (rect), height = NSHeight (rect); | 8349 | int width = NSWidth (rect), height = NSHeight (rect); |
| 8325 | 8350 | ||
| @@ -8327,7 +8352,6 @@ not_in_argv (NSString *arg) | |||
| 8327 | block_input (); | 8352 | block_input (); |
| 8328 | expose_frame (emacsframe, x, y, width, height); | 8353 | expose_frame (emacsframe, x, y, width, height); |
| 8329 | unblock_input (); | 8354 | unblock_input (); |
| 8330 | #endif | ||
| 8331 | } | 8355 | } |
| 8332 | 8356 | ||
| 8333 | 8357 | ||