Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #3761, #2886 - Draw and Layout performance issues #3798

Open
wants to merge 179 commits into
base: v2_develop
Choose a base branch
from

Conversation

tig
Copy link
Collaborator

@tig tig commented Oct 15, 2024

Fixes

Related

Proposed Changes/Todos

  • Decouple layout from draw
  • Refactor View.LayoutSubviews etc... to make more testable and clearer to use. Introduce View.Layout() as the primary API that builds on View.SetRelativeLayout and View.LayoutSubviews. Move from depending on IsInitialized to NeedsLayout as the signal that layout has been performed.
  • Refactor View.Draw to be more granular and use proper event patterns.
  • Minimize when Draw/OnDrawContent are called
  • Enforce that Clear rarely happens
  • Add View.SetAttribute; make Driver.SetAttribute internal
  • Add non-rectangular clip regions - Improve redraw performance by making Clip be a Region instead of Rectangle #3413
  • Refine non-rectangular clip regions - some edge cases not working like shadowview
  • Undo "fix" to Enabled to enable disabled views to stay disabled even if superview changes; use an event instead of hacky logic.
  • Remove all refs to Driver.Move/AddStr
  • Ensure drivers minimize full repaints
  • Test other drivers

Pull Request checklist:

  • I've named my PR in the form of "Fixes #issue. Terse description."
  • My code follows the style guidelines of Terminal.Gui - if you use Visual Studio, hit CTRL-K-D to automatically reformat your files before committing.
  • My code follows the Terminal.Gui library design guidelines
  • I ran dotnet test before commit
  • I have made corresponding changes to the API documentation (using /// style comments)
  • My changes generate no new warnings
  • I have checked my code and corrected any poor grammar or misspellings
  • I conducted basic QA to assure all features are working

tznind and others added 30 commits September 9, 2024 20:39
@tig
Copy link
Collaborator Author

tig commented Oct 29, 2024

lXMhxsU 1

This vid demonstrates non-rectangular clip regions doing their magic!

@dodexahedron
Copy link
Collaborator

Loving the work on this. 👍

Planning to take a good look at the code later today.

@tig
Copy link
Collaborator Author

tig commented Nov 2, 2024

The current state is pretty good with the exception of:

  • Shadows (actually Margin in general) are broken
  • ScrollView is broken (and I won't fix... we have a new one coming)
  • TabView is broken. Bdisp has a pr i haven't had a chance to look at.
  • Attribute setting is brute force. Need to really clean that up because Color comparison is a heavy op.

I have not invested as much energy in unit tests as I've liked.

@tig
Copy link
Collaborator Author

tig commented Nov 3, 2024

This is how this all works (from drawing.md):


Drawing occurs each MainLoop Iteration

The @Terminal.Gui.Application MainLoop will iterate over all Views in the view hierarchy looking for views have their @Terminal.Gui.View.NeedsDraw property set. The @Terminal.Gui.View.Draw method will be called which, in turn:

  1. Sets the clip to the view's Frame.
  2. Draws the @Terminal.Gui.View.Border and @Terminal.Gui.View.Padding (but NOT the Margin).
  3. Sets the clip to the view's Viewport.
  4. Sets the Normal color scheme.
  5. Calls Draw on any @Terminal.Gui.View.Subviews.
  6. Draws @Terminal.Gui.View.Text.
  7. Draws any non-text content (the base View does nothing.)
  8. Sets the clip back to the view's Frame.
  9. Draws @Terminal.Gui.View.LineCanvas (which may have been added to by any of the steps above).
  10. Draws the @Terminal.Gui.View.Border and @Terminal.Gui.View.Padding Subviews (just the subviews). (but NOT the Margin).
  11. The Clip at this point excludes all Subviews NOT INCLUDING their Margins. This clip is cached so @Terminal.Gui.View.Margin can be rendered later.
  12. DrawComplete is raised.
  13. The current View's Frame NOT INCLUDING the Margin is excluded from the current Clip region.

Most of the steps above can be overridden by developers using the standard Terminal.Gui cancellable event pattern. For example, the base @Terminal.Gui.View always clears the viewport. To override this, a subclass can override @Terminal.Gui.View.OnClearingViewport to simply return true. Or, a user of View can subscribe to the @Terminal.Gui.View.ClearingViewport event and set the Cancel argument to true.

Then, after the above steps have completed, the Mainloop will iterate through all views in the view hierarchy again, this time calling Draw on any @Terminal.Gui.View.Margin objects, using the cached Clip region mentioned above. This enables Margin to be transparent.

Declaring that drawing is needed

If a View need to redraw because something changed within it's Content Area it can call @Terminal.Gui.View.SetNeedsDraw. If a View needs to be redrawn because something has changed the size of the Viewport, it can call @Terminal.Gui.View.SetNeedsLayout.

Clipping

Clipping enables better performance by ensuring on regions of the terminal that need to be drawn actually get drawn by the @Terminal.Gui.ConsoleDriver. Terminal.Gui supports non-rectangular clip regions with @Terminal.Gui.Region. @Terminal.Gui.ConsoleDriver.Clip is the application managed clip region and is managed by @Terminal.Gui.Application. Developers cannot change this directly, but can use @Terminal.Gui.Application.ClipToScreen, @Terminal.Gui.Application.SetClip(Region), @Terminal.Gui.View.ClipToFrame, and @Terminal.Gui.ClipToViewPort.


I am now working through what it would mean to have Border be treated like Margin above: Be excluded from the Clip of a View and rendered in a 2nd pass. This should make the whole LineCanvas thing work much more cleanly.

@tig tig requested a review from BDisp November 4, 2024 20:54
@tig
Copy link
Collaborator Author

tig commented Nov 4, 2024

This is now ready for real review.

Still some to do, but mostly unit tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants