Thank you Matt for a very detailed and thorough reply! This is very useful and clarifying information.
> On 17 Dec 2018, at 20:39, Matt Jacobson <matthew_jacob...@apple.com> wrote: > > Even if it were, it’s still unsafe to ignore the rect passed to -drawRect:. > That’s because the system might require you to redraw a larger area than what > your code thinks needs to be redrawn. Speaking of this, getRectsBeingDrawn: doesn’t seem to work outside of drawRect:, e.g. in displayLayer:. Is there any way to get at CA/AppKit’s view of what needs redrawn another way? Without this information we’re forced to do full updates on every repaint, even when originating from say setNeedsDisplayInRect:CGRectMake(50, 50, 10, 10). >> (I know this is a bad ida, but) is there a way to achieve the same >> synchronous flush with layer-backing? > > No. > > The imperative view drawing model you’re describing has long been > discouraged. Among others problems, imperative drawing disrupts the drawing > of overlapping views (both siblings and superview–subview pairs), is > incompatible with layer-backed views, and prevents system drawing > optimizations. Right. We are aware of the situation. Unfortunately Qt’s Widget module assumes an imperative drawing model. During AppKit driven updates the flow goes something like this: - [QNSView drawRect:] or [QNSView displayLayer:] (depending on whether layer-backing is enabled or not) - QCocoaWindow::handleExposeEvent(dirtyRegion) - QWidgetBackingStore::beginPaint() - QWidgetBackingStore::endPaint() - QWidgetBackingStore::flush() - QCocoaBackingStore::flush() - a) non-layer-backed - [view lockFocusIfCanDraw] (if there’s no focusView) - [backingStoreImage drawInRect:] - [view unlockFocus] and [view.window flushWindow] (if there was no focusView) - b) layer-backed - view.layer.contents = CGImageFrom(backingStoreImage) But when QtWidget drives an update, say after clicking a button, we end up with: - Qt’s CFRunLoopSource for posted events - QWidgetWindow::event(QEvent::UpdateRequest): - QWidgetBackingStore::beginPaint() - QWidgetBackingStore::endPaint() - QWidgetBackingStore::flush() - QCocoaBackingStore::flush() - a) non-layer-backed - [view lockFocusIfCanDraw] (if there’s no focusView) - [backingStoreImage drawInRect:] - [view unlockFocus] and [view.window flushWindow] (if there was no focusView) - b) layer-backed - view.layer.contents = CGImageFrom(backingStoreImage) https://github.com/qt/qtbase/blob/5.12/src/plugins/platforms/cocoa/qcocoabackingstore.mm#L81 A similar situation happens when an animation is driven by a CVDisplayLink, where the display-link callback coming in on the secondary thread is delivered to the main thread via dispatch_source event handler, so we’re again drawing & flushing outside of the display cycle. https://github.com/qt/qtbase/blob/5.12/src/plugins/platforms/cocoa/qcocoascreen.mm#L270 If we can’t (shouldn’t) do any imperative drawing, should a CVDisplayLink callback always just call setNeedsDisplay and let the callback be coalesced into the main runloop's display cycle? Even for OpenGL or Metal, where you can present a frame imperatively? > • using -[NSImage initWithSize:flipped:drawingHandler] to capture > drawing code into a block; by drawing that image in -drawRect:, you’ll defer > execution of the drawing code until then This one looks interesting! > > I hope this helps! Very much so, thanks again!! 😊 Cheers, Tor Arne _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com