[haiku-appserver] Re: drawing thread

  • From: Adi Oanca <adioanca@xxxxxxxxxxxxx>
  • To: haiku-appserver@xxxxxxxxxxxxx
  • Date: Tue, 19 Oct 2004 16:40:06 +0300

Hi,

        Sorry for the delay, I was out of town for a few days. :-)

DarkWyrm wrote:
>>>Yes we are. Double-buffering is internal to the display module and 
>>>is 
>>>not a requirement -- AccelerantDriver is currently not double 
>>>buffered, 
>>>for example, even though I'm assuming that it eventually will. The
>>
>>      It can be seen we haven't talked in a long time. :-)
>>      I don't know how double buffering at DD level could work. In fact, 
>>I'd really like you to explain 
>>us, cause' you're making me very curious.
> 
> The actual DisplayDriver class doesn't actually do anything with 
> respect to double-buffering -- it's actually up to the subclass. I'll 
> use the now-obsolete ScreenDriver and DirectDriver as examples. 
> DirectDriver's architecture is set up such that gfx calls are written 
> to a BBitmap and updated rectangles are put into a FIFO pipe which the 
> updater thread pulls rectangle. AcquireBuffer calls return a pointer to 
> the BBitmap. As such, it very much is double-buffered.

        Heh, that's not double buffering. That's plain bitmap drawing. :-)
        I really don't how are you going to do this. I have explained how this 
could be done, now I'm asking you to give me an elaborate explanation 
because I'm not getting anything. :-( :-)

        If you want to do d.b. at DD level, the _only_ way I see it, is by 
buffering every Layer, and in DrawData you should have a pointer to 
Layer's associated [off-screen]bitmap. If you ask me, that's bad. You 
have to allocate dozens of areas each one containing one Layer's data, 
not even talking about the semaphores needed to access them. As far as I 
see it, d.b. should be done at window/WinBorder level. Allocate an 
off-screen surface(area) to hold entire window's surface and each view 
should write into that area. When updating is done, blit on-screen.

> Calls in 
> ScreenDriver (before I really broke it) wrote directly to the 
> framebuffer. IIRC AccelerantDriver calls HW-acceleration functions 
> where appropriate and otherwise uses software calls to write directly 
> to the frame buffer.

        DD is free to chose the best way to do things. The double buffered 
window manager is not concerned how drawing is done or if the blitting 
process is HW accelerated.

>>      My opinion:
>>      I think you are wrong. DisplayDriver is a drawing framework. How it 
>>gets things done it's its 
>>business, it can directly use hardware acceleration or use CPU to 
>>draw in buffers.
>>      You do not need to lock it to use its methods. Instead, those 
>>methods should get a buffer and a 
>>drawing context. Based on those arguments, it draws within specified 
>>clipping region inside buffer. 
>>This way you need not to lock DD, and in a multiprocessor environment 
>>is could be a very good thing 
>>as another CPU could safely draw onscreen the contents of other 
>>windows.
>>      Double buffering needs to be controlled by window manager because 
>>it is the one that issues 
>>_UPDATE_ requests. When redrawing of a window is needed, it can very 
>>easily look into window's 
>>offscreen buffer to see what valid areas it has and what exactly 
>>needs to be actually redrawn.
> 
> What about when two different threads need to write to overlapping 
> areas of the screen?  An excellent example would be when a developer
> goofs and overlaps two sibling BViews.

        DW, come on... Why do we calculate visibility regions? Why do we always 
draw from back to front?
        OK, to answer to precisely:
        With the help of visibility regions, if two views overlap, it is always 
that the newest view will get the common region. The result: the old 
view will draw in it's full_region-common_region, the new view in 
full+region+common_region.
        If the newest view is transparent, then the visible region of the older 
view will contain the common region also, and the back to front drawing 
order will assure us the correct result is shown.
        And to add the final ingredient:
        Didn't we agreed blitting will be made from on thread only? 
PollerThread?

> up or keeping both copies up-to-date gets pretty hairy when screen 
> composition is done.

        That's why access to an off-screen surface will be guarded by a 
semaphore. ;-) Imagine the number of semaphores you'll be needing if you 
want to cache every Layer. :-))
        If I'm thinking better, there is no point in doing double buffering at 
Layer level because we'll be using much more memory when, in fact, we 
only show "a fraction" of it - visible_region. And if we do that, what 
we'll be using as a reference for the off-screen bitmap size? 
full_region? BAD idea, as it can be very big! visible_area? Yes, that's 
OK, but then again isn't this what we exactly cache if we only cache the 
entire window?
        Wait there is more: if we cache a Layer and it has a child right in the 
middle of it which occupies 90% of its surface, how do we allocate the 
associated off-screen bitmap? If we make it after the full or visible 
region them we'll end up with a 90% unused bitmap. BAAAAD! :-)
        Same is valuable of off-screen windows/WinBorders, but this is at least 
justified, as it's the reason why we do double buffering.

> Parallel access like what you describe is 
> something that I want for after R1 -- not before.

        A big NO.
        Unless you have a simpler or faster :-) or easier to implement 
solution... :-)
        Plus, we don't have any code in place for d.b.!

> Locking is necessary 
> because we are heavily multithreaded.

        Of course, when needed! If it can be avoided, WHY NOT?

>>      Locking is needed only when double buffering is disabled or when we 
>>go out of memory for the double 
>>buffering process. Still, in the second case we could release the 
>>memory of some minimized or rarely 
>>used windows.
>>
>>
>>>BitmapDriver, for example, is also not, but for obvious reasons. 
>>>Any 
>>>time we have two threads sharing access to a common resource, such 
>>>as 
>>>DisplayDriver, there is a need for locking -- unpredictable results 
>>>occur otherwise.
>>
>>      Guess you have a different opinion now. :-) Isn't it? :-P
> 
> Not at all.

        You should have now. :-))

> My opinion has stayed the same. What you are proposing for 
> changes to the DisplayDriver system is more like what Longhorn has 
> done, and the entire system is definitely something that will work, but 
> it's also an order of magnitude different from what's in place.

        Don't care about Longhorn. The link I gave you was just to show you 
what I already had in mind. I've been thinking about d.b. for maaaaany 
months. :-)
        Why are you under impression the DD that I'm proposing is that 
different from what is in place? I think we have 99% in place. What is 
needed, is that every drawing instruction should have the off-screen 
buffer to draw into as a parameter. That buffer is already locked with 
the help of Acquire/ReleaseBuffer(FBBitmap *bmp);
        Now think a bit, if we disable d.b., we'll be using one buffer only, 
the frame buffer, and that's 99% of what we have now. We only need that 
extra parameter.

> I hate 
> to sound like I don't care about what you think -- I do -- but we need 
> to stick with what we've got.

        We don't have double buffering code!

> If we keep doing major redesigns of 
> significant portions of the app_server, we will _never_ finish.

        Sure we will. App_server design will be ready the day we reach BETA 
stage (fully functional, but with bugs). Until that moment we must do 
the best we can. Notice that, I DID NOT said nothing about 
optimizations, only about re/design.

> At this 
> point, that is the major goal I've got in store is to push so that we 
> actually have an alpha sometime next year.

        I'm sure we will.


Regards,
Adi.


Other related posts: