 Hello, I'm Kendi, I work for Collabora and the work that I'm going to present here is not mine, in that large extent it's mostly done by Miklos and Tomasz, who have done all the heavy lifting, so I'm here on the stage, but the real guys are, well, not even any of the audience, but maybe they will come. Anyway, so VCL, VCL is our toolkit that is responsible for all the drawing on the screen that you can see in the LibreOffice. It has some quite long history from what I know, it is about 20 years or something like that. And thanks to that, well, it can be a bit twisted in some places. On the other hand, it's what we have, and over the years it evolved into something that is like cross-platform, usable with the most modern Linux systems, Windows system and everything, so it's good enough, and well, we have to love it because it's what we have. So the rendered context work that I'm going to present here is just part of the work that has been happening for 5.0. For the other pieces, please just come to the talk that is just after my talk. Michael will talk about lots of things that actually were necessary in order for this rendered context to be actually possible. So the basic question that we have to play here in order to be able to do double buffering was when do we actually draw? So in VCL, or in LibreOffice in general, we can draw in many places, and that is when painting. So that means that when the paint method is actually triggered by VCL, main loop. This is okay. This is what we need. This is what is necessary. But also in many places it happens that it is called in event handlers, so you press a key and something is directly drawn on the screen. You put mouse over a widget and it is drawn directly, and this is not what helped us. Also in some cases the painting can be actually triggered by timer. So there is some timer that goes on and on and sometimes it just paints something on the screen somewhere in the corner where the user notices that or not. And also it can be at the render time. So like in the right turn there is a layout algorithm that is triggered from time to time for things. And in the debug mode we have a small rectangle in the top left corner that indicates if the layout is finished or not yet, and that is done by direct drawing as well. Compared to that the ideal state would be just to have the painting triggered in a controlled way. So it would mean that only the paint method actually paints and we are able to know when it happens. So in the ideal state it would be triggered only by the ECL, so only in the given time when we have the complete control over the things that are happening. So this way we can much better control what is happening, like do various setups and teardowns that might be necessary for example for OpenGL. To be able to do that actually we have to avoid the direct painting. So we have to only invalidate the area and let it up to ECL to find the correct time for triggering the paint itself. And based on that ECL decides what to paint where, if to paint bigger area, smaller area and everything. And also in the ideal state we would like to decouple the actual painting from the VCL window. So that means that it wouldn't be impossible to call some drawing on itself on the window. So in that case the VCL window would become a bit more abstract. But on the other hand it would allow us to discourage people very intensely from trying to draw directly. So I've mentioned render context, so what's that? So that's a class that implements the drawing itself. So when we decouple the window from the render context it means that the render context itself is responsible for the lower parts of the drawing. So render context would contain the methods to paint rectangle, paint a line and things like that. But not through the window. Currently it is so that the VCL window is inherited from the output device. So it means that it allows the programmer to actually call painting on itself, directly calling some drawing, triangle, draw, whatever and we want to avoid that. Instead the render context would be the implementation of the output device. It would contain, it would be the only class that would actually have access to these things, to the painting. And it would be by VCL passed as a parameter to paint methods so that when you are painting in the paint method you have this render context where you can do the operations that are necessary. Actually, what is wrong with the dirt paints? Why do we need to do this at all? So in cases like as I was talking about in these cases when we triggered the drawing directly from the code from some higher levels than from VCL we actually do not have the render context. So it means that in the idle state when we get rid of the or when we split the VCL window to not to be actually inherited from the output device it means that the direct draws wouldn't have the possibility to actually set up the render context themselves. So we needed to do the cleanup here and also we needed some other pieces in the VCL change and that also like the idle work that actually made the invalidates fast. So previously invalidates were triggered by timer, it is not so anymore. But this changes to make actually the invalidate work have to be done carefully because if you just change the direct draws to invalidates without testing and without thinking you can easily come to a situation when you cause an invalidate loop. So it means that you will come to the code that causes an invalidate which then causes draw and then it again causes invalidates and you are in a loop. So we had several of these and had to fix that. And how it actually fits the double offering. So the double offering is what we want to achieve here and that means that the content is not drawn directly on the screen but first it is drawn into a buffer that is then copied to the screen. This allows you to avoid flickering, for example, when you are resizing windows or when you are painting like more, for example, widgets that are more hard to paint like there are many operations that need to be done in order to be painted. So with this to achieve the double offering when we have the render context we can do quite relatively easy changes in the main paint engine that is in VCL that is responsible for the rendering and we do it so that we can set up the buffer for the double buffering first then do the paints as we were doing before or very similar to as we have been doing before. And then when we are done with this painting we can copy it back to the screen again. So when we have done the heavy lifting of the render context then the double buffering is there nearly for free, one would say. But the render context work was the hard part so it had an easy part which was adding the parameter to the paint methods which was possible using as plain power game but on the other hand everything else was just hard. So thanks so much to Tomasz and Miklos who were doing all the heavy lifting there and also Laszlo and others fixing the consequences that were necessary to be done after the render context work. So just to show you some of these examples what were the hard parts here so in many cases the drawings in the paint as it was before we have done lots of this work in the render context were very stateful. So it means that in the constructor of some widget you have set up for example the background of what you were drawing and also colours of the fonts and stuff like that and later when it came to the paint it was just expected that it is all there, it is all set up and that you can just hold the drawing methods. This is not the case with the render context anymore you have to do these setups directly in the paint method because the render context is supposed to be set up from scratch and so the paint itself has to be stateless. In many cases in the Libreface code the output device was actually cached so in many cases it was so that some code did some drawing then remembered the output device in a member variable and then in some completely unrelated pieces of the code then again tried to access this cached output device which of course works with the drawing but it doesn't work that well when you have the render context actually valid only for the time of the painting. Then Blinking Cursor, Blinking Cursor is another hard part because how is it implemented now is that it actually inverts the background or the picture that you have on the screen so it just inverts that and it again doesn't work that well with the render context that can be like whatever big buffer that is alive only for the time of the painting and later when you are making the Blink using the direct drawing or in some random time, you can fetch the image from the screen actually but it's just very slow and something that you don't want to do and one of the challenging things was actually that the render context can actually have a different size compared to the window itself so it was necessary to be careful what pieces in which parts of the paint you need the size of the target device of the render context where you are painting to and where you are actually referencing the size of the entire window for example when you are counting like how to place something in the middle of the screen or something like that. So current status, so most of the classes were modified to paint only the paint methods now it is so that all the paint methods have the render context as a parameter and most of them have been reviewed to be able to see that they are correct with the render context startCenter now completely uses double buffering so it is flicker free now writer is mostly double buffered except there are still some things that need some improvements I think in cursor it's one of the examples most probably we would like to change to the way that for example Mozilla is doing that it doesn't invert the content that is behind but instead uses just draws the rectangle over that like thin but just a rectangle and you can try it yourself it's very nice in master and mostly in 5.0 as well so if you when you explore this VCR double buffering force enable then you can see and I will also try to show it to you if you can see here I cannot see it here that well this is the non double buffered case so you can see that when you are moving it blinks like crazy and when I call it with this VCR double buffering force enable it is just completely smooth so unfortunately the break is still not finished so for the text cursor I've already mentioned it would be good to get rid of the inverting and just draw the rectangle the next thing would be switching on for the startCenter and writer so that it is used in master and people can report bugs in case they see them which is a bit challenging because currently it is so that you have the startCenter and when you start some application inside the startCenter it reuses the window so it can be that you have the startCenter and you start calc and then it starts appearing directly in the startCenter window so we just need to make sure that we are able to switch the double buffering off in case awesome, awesome, so we should just switch it on, sorry so MiGlosh as I said and Comanche are the neurons here so just do it and before that I've got to use the double buffering force awesome, awesome, let's switch it on the master thank you so much cleanup once we are using the double buffering like seriously there are still some things that we had to introduce like if double buffering do it a bit differently than if not double buffering so for the cases where we are already doing the double buffering of the buffering and we can clean that up so that it always uses the double buffering code path and also the small thing of implementing it for calc and pressing, thanks sure, question how do you deal with your back and buffer, the place of the temporary write it's a big method with one DPI the number of pixels per bother, the resolution of it how do you deal with the fact that you have a window that could be across two different screens with one retina, one now so no, your virtual thing, you think it's the same thing but when you display it, if you don't draw it directly when the system compensates for the fact that this half of the window is physically twice the density than this half what's it going to look like when you start to put a bitmap on it directly okay, so I just repeat the question so what happens if you have two screens of various DPI's are you doing the same thing? yes, so this is something that the interface doesn't handle by itself either way but today because we draw directly the system to that point, on math it will compensate and do twice more pixel because he knows what it is so I never tested this possibility so I should that seems to be a scam okay well it's not the same so further, we are using and increasingly using the tile rendering of all many things so the ideal here would be not to use tile rendering only for Android and LibreOffice Online but to actually use it for desktop application as well so that there is again just one code path that needs fixing, debugging and everything and also it would allow things like we are doing on LibreOffice Online that you are actually able to cache more than you see on the screen so the scrolling is just extremely fast and yeah of course the scrolling is much faster and much nicer but again that would be the next step there I suppose that it's not going to happen in the next few months let's see so that's all for me how much work is left in Calc and in other places? the question was how much work is left in Calc and in other places and to answer that, I don't know, we can just try it here see how much programming it is if it is the double buffer, yes, there is the double buffer one so yeah, you can see well, at least the toolbars work it's mostly miscellaneous, so it's not completely terrible a lot one place in the game fixed the whole sidebar well it was so like there were like bugs that were hard to fix but once you fix that, half of it started to work I think it's not that like thank you so much