[interfacekit] Clipping - what to do, what to do?

   Hello!
 
   Here is a problem for you all: How can we clip drawing instructions?
 
   Let me start by telling you what the problem is. Suppose we have the
   following scenario:
 
   22222222222222
   22222222222222
   1111122222222222222
   1111122222222222222
   1111122222222222222
   1111111111111
   1111111111111
 
   Two windows, window '2' overlaps window '1'. What we see here are the
   visible parts of the two windows. Now, let's not refer the them as being
   windows, but... layers.
   When we decide to draw in a surface, we _must_ draw _only_ in its visible
   area, thus when we draw a line from top-left to top-right in layer '1',
   only 5 dots will be actually drawn. That is what lower level clipping is
   about. The line example was a "happy" case, consider drawing a filled oval
   inside surface '1'!
   Well... how are we going to do that?
   Oh, not to forget! 99% of drawing primitives are implemented in software
   by directly writing in the frame buffer. 2D acceleration can only draw one
   color rectangles and invert them.
 
   I have come up with 2 solutions, of course each with its advantages and
   disadvantages.
 
   We could do it the "hard" way, by checking every pixel if it is in the
   visible region, by invoking BRegion::Contains(pt), but this will be
   overkilling for the CPU. This has the advantage that it requires no
   additional memory.
 
   The second proposal, and the one that I vote for, is by using a memory
   region equal to BRegion::Bounds(). Every layer that needs a part of it to
   be redrawn has a valid fUpdateReg region. This is the region in which,
   this layer is allowed to draw - the clipping region. It is a part of the
   visible region, and it is the minimum region required to be updated.
   When an update is required(of forced: by calling ::Invalidate()) the
   following happens:
   * [fUpdateReg already is valid]
   -> an _UPDATE_ message is sent to client side(BeApp)
   -> just before calling BView::Draw() BWindows inserts a _WILL_DRAW_ to be
   sent to the server.
   -> ::Draw() gets called and all drawing is done.
   -> when ::Draw() finishes, _END_DRAW_ is added to queued messages to be
   sent, and a Sync() is made.
 
   What do you say if, when we receive _WILL_DRAW_ we allocate(with malloc) a
   memory region the size of fUpdateReg.Bounds()/8, and we set every bit to 1
   if that (x,y) coordinate is in the region, 0 if not.
   Please _do not_ start wondering "Why not use one byte per pixel to achieve
   transparency (0-255)?" This _only_ concerns clipping, so leave
   transparency aside!
   When we want to paint a pixel, we can determine very quickly if it is
   visible or not. Using this method, all drawing instructions(d.i.) found
   inside BView::Draw() are executed, and when app_server receives
   _END_DRAW_, the allocated memory region is deleted. OK, maybe not deleted
   if there are still views that need to be updated, and we could use
   realloc() for them.
   Memory used for this operation is not that much as you might have thought.
   Every surface is managed by an app_server thread, and at a given moment,
   it only draws for _one_ surface, and only one memory region is used by all
   surfaces associated with that specific thread.
   Now you would say: OK that was for the update mechanism, what if drawing
   is made from outside ::Draw() of from another thread? IMO, the answer is
   quite simple. Because BWindow thread must be locked, all drawing
   instructions are serialized so all d.i. are from outside ::Draw(). When
   the first d.i arrives at server, a memory region equal to
   layer::_visibleRegion.Bounds() is allocated to help with the clipping
   process. The second, third,... d.i. still use this memory region assuming
   layer's visible region was not modified. If it was, the memory region is
   freed and a new one will be created when the next d.i. arrives. Finally,
   if no d.i. is received in half a second, it is deleted(freed). [how???]
   There is a concern about Resize/Move methods inside ::Draw(), but this a
   problem that is not of immediate priority.
 
   Well, what do you think? Is this algorithm good enough? Other ideas?
   Improvements?
   I don't know how clipping is done in Windows or Linux/UNIX, so, if anyone
   knows, please tell us.
 
   Regards,
   Adi.


---------------------------------------------------------------
Trimite celor dragi cele mai frumoase felicitari de Paste prin 
http://felicitari.acasa.ro

Other related posts: