gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Some diffs to optimize drawing


From: Benhur Stein
Subject: Re: Some diffs to optimize drawing
Date: Wed, 5 Feb 2003 22:51:44 -0200
User-agent: Internet Messaging Program (IMP) 3.0

Sorry for taking so much time to answer.
I was writing a huge mail monday and just before hitting 'Send',
electricity went off :-(
I'll try to rewrite it.

Citando Nicola Pero <address@hidden>:

> > So ... I agree that this change is the 'right' thing to to, but it's quite
> likely it
> > has still been masking some other problems, and we need to look out for
> > and fix them as soon as we can.
> 
> Definitely in the sense that all these changes to locking/drawing are very
> delicate.  Probably the lockFocus didn't break much (unless we've
> forgotten to update a caller); what might have broken things in
> non-trivial ways is that Benhur also tried to remove some of the
> inefficient redrawing in NSMatrix, where a lot of code was redisplay to
> screen immediately instead of marking stuff as needing redisplay (and
> letting them be redisplayed later in a single sweep).  This sort of
> changes is very delicate, selections were involved etc.
> 

I think that it should not be so difficult..
I tried to organize my thoughts on this.
There surely are problems that didn't occur to me.
Please tell me what you think.

I see three kinds of methods involved in drawing (mostly in views/cells):

- methods that do the real drawing (mostly named drawSomething);
- methods that change the state of something so that its visual representation
  should be changed. These methods know what has to be drawn, but not when.
- methods that need things to be on screen immediately.
  Typical case is before asking for an event (tracking mouse) or before sending
  an action.

Of course there are the exceptions or special cases or things I didn't think 
of...
But it seems to me that most methods that affect the display of things can be
classified in one of these types. The classification of a method in the second
or third kind is what poses more problems, as sometimes it is difficult to
identify what should be done. Sometimes the documentation of openstep is not
clear enough and some of the methods (mainly newer ones) are not very 'NeXTish'.

Methods of the first kind are easy: they are called with focus locked,
they just do the drawing and do not call flushWindow. In most cases, they
are called from display.. methods, that do the focus locking and flushing.
They can be directly called by other methods of the same kind (that are drawing
in the same view), but methods of a different kind must lock/unlock focus and
have the window flushed. 

Methods of the second kind are the ones where time can be gained by accumulating
the drawings that need to be done and doing them all at once. So, I think that
these methods should only call setNeedsDisplay... and not do any real drawing.

Methods of the third kind are a bit more complicated and are much less
optimizable. An easy way to implement them is to use methods of the second kind
and call displayIfNeeded when everything must be on screen. Another way is doing
the drawing (directly or calling draw methods). In this case it must take care
of focus and flushing. Yet another way is using a mix of the two (which I think
should be avoided)..

So, when are the views updated?
- automatically: all views that needDisplay are drawn by their window, in two
  different automatic ways (that I could find in current code):
  - when the window is marked as needing display, it asks the runloop to perform
    _handleWindowNeedsDisplay before running the next time. This method calls
    displayIfNeeded, that calls view's displayIfNeeded that does all the
    lockFocus drawRect unlockFocus flushWindow for each view in the hierarchy
    marked as needing display.
  - after each event is processed, NSApplication sends -update to each window
    that needs to be updated. This method also calls displayIfNeeded (if the
    window is marked as needing display), but brackets it with
    disableFlushWindow and enableFlushWindow, flushWindowIfNeeded. (And
    unconditionally flushes the current context, I'm not sure why, probably to
    correct some bug in flushing elsewhere).
  Here I see a problem, the two methods behave differently. I propose (and it is
  in the patch I've sent) to put this bracketing to disable flushwindow inside
  the displayIfNeeded method, because the way it is the flushing in each subview
  will be performed, causing delays and flashing. With this bracketing in
  displayIfNeeded, it is not necessary in -update. The call to
  flushWindowIfNeeded is outside the conditional probably because of the same
  bug in flushing. The problem is that sometimes when these update methods are
  called, the window does not need to be displayed, but needs to be flushed, and
  this seems to be a bug (problably methods of the third kind above that are not
  calling flushWindow). Sometimes in this situation (when flushing is necessary,
  and displaying is not), the update methods are not called, and the flushing
  bug shows. Because of this, I suggested to change NSWindow to ask for the
  execution of this _handleWindowNeedsDisplay method not only when display is
  needed, but also when only flushing is needed (unlockFocus know when flushing
  is needed and already change the window's state to reflect this). The other
  solution is to correct all code (of the third kind) to make sure the window is
  flushed.
  I also wrongly suggested in the patch to remove the -flushWindows from the
  view's display methods. This part of the patch is wrong.
  
- manually: these are the methods of the third kind. They should do the whole
thing and not expect for some automatic displaying or flushing (unless we
implemented the automatic flushing, that would solve some (but not all) of the
cases.)

Time-out, I must go. Hope this is somewhat useful.

Comments?

Benhur




reply via email to

[Prev in Thread] Current Thread [Next in Thread]