When switching pluggable presenters, I want to eliminate flicker--unwanted
or unnecessary redrawing of the background of the container. Where do we typically disable background repainting? InvalidateRect? I'm assuming that Windows is painting each background in positive z-order (right-handed coordination) from back-to-front--frame, container, pluggable, in that order. If my pluggable is rendered in OGL, there is no flicker because of the double-buffering. But I still need to kill redraw of the container and window, so that the white flashes are not seen. Suggestions are welcome. Shaping |
Shaping wrote:
> When switching pluggable presenters, I want to eliminate flicker--unwanted > or unnecessary redrawing of the background of the container. Where do we > typically disable background repainting? InvalidateRect? There are a number of techniques for reducing/eliminating flicker, I don't know which, if any, are applicable in your case. 1) override View>>onEraseRequired: in your View class to do nothing except answer 1, thus telling the framework that you are handling the erase yourself. Only really makes sense for custom views. 2) View>>disableRedraw and #enableRedraw can be used to reduce the amount of flicker as a view repeatedly repaints itself. 3) Avoid sending #invalidate to a ShellView. That causes the entire shell, including its title-bar and borders, to repaint -- and looks /terrible/... 4) Set the background of the container presenter (PlugholePresenter in my example) to a colour as close to the average/background colour of your pluggable views as possible. 5) (Pretty dodgy, but I do it anyway ;-) When you change the Model of a non-trivial presenter it will (naturally) pass the model over to its View too. In many cases (in fact without exception, in my code) "interesting" presenters are connected to container views. Allowing the container to "see" the new model causes it to refresh itself needlessly ("needlessly" since it doesn't actually /use/ the model). So I sometimes just assign to 'model' directly in my presenter's #model: rather than doing a super-send. I /think/ that there may be a non-dodgy equivalent by doing something like overriding #viewModel, but I've never looked into it. -- chris |
> There are a number of techniques for reducing/eliminating flicker, I don't
> know > which, if any, are applicable in your case. Thanks, for the suggestions, but I can't seem to stop the blanking to white in containers. Does anyone else have any success with preventing repainting of container backgrounds? > > 1) override View>>onEraseRequired: in your View class to do nothing except > answer 1, thus telling the framework that you are handling the erase > yourself. > Only really makes sense for custom views. I tried this in the PresenterPresenter's (PlugholePresenter's) view, but it still repaints itself white before repainting the contained view. > > 2) View>>disableRedraw and #enableRedraw can be used to reduce the amount > of > flicker as a view repeatedly repaints itself. Doesn't this trigger downward to contained views. In other words, if I #disableRedraw at the container, will the contained view every be redrawn? > > 3) Avoid sending #invalidate to a ShellView. That causes the entire > shell, > including its title-bar and borders, to repaint -- and looks /terrible/... > Agreed. > 4) Set the background of the container presenter (PlugholePresenter in my > example) to a colour as close to the average/background colour of your > pluggable views as possible. I tried this but it doesn't work. I still get the white flashing, then the container background redraw, and then the pluggable presenter's view's background redraw. > > 5) (Pretty dodgy, but I do it anyway ;-) When you change the Model of a > non-trivial presenter it will (naturally) pass the model over to its View > too. > In many cases (in fact without exception, in my code) "interesting" > presenters > are connected to container views. Allowing the container to "see" the new > model causes it to refresh itself needlessly ("needlessly" since it > doesn't > actually /use/ the model). So I sometimes just assign to 'model' directly > in > my > presenter's #model: rather than doing a super-send. I /think/ that there > may > be a non-dodgy equivalent by doing something like overriding #viewModel, > but I cannot comment-out the super send without breaking the present code. I will investigate further. Shaping |
Shaping wrote:
> > 2) View>>disableRedraw and #enableRedraw can be used to reduce the > > amount of > > flicker as a view repeatedly repaints itself. > > Doesn't this trigger downward to contained views. In other words, if I > #disableRedraw at the container, will the contained view every be redrawn? I'm not quite sure what you mean here, so I may be trying to answer the wrong question. If you send #disableRedraw to a container view, then (as far as I know) that view, and all it's subviews will stop repainting themselves until the container is sent #enableRedraw. When that happens, it will #invalidate itself automatically, which will cause Windows to ask it (and hence its subviews) to repaint themselves. So you will always get /one/ redraw. The "value" of the technique is to avoid flickering if the various views redraw themselves several times during a re-configuration. > > 4) Set the background of the container presenter (PlugholePresenter in > > my example) to a colour as close to the average/background colour of > > your pluggable views as possible. > > I tried this but it doesn't work. I still get the white flashing, then > the container background redraw, and then the pluggable presenter's view's > background redraw. Maybe you are setting the background to the wrong container ? I'd try setting the background of /every/ container to a different colour (and one that is clearly not white), and see what colour got flashed then. If it's still white then at least you know you have to look at a deeper level (maybe at the Windows level) for a solution. I've tried technique (4) on my example -- setting the pluggable presenters' colours to deep blue so that flashing should show up more clearly, and it seems to work pretty smoothly. But then, those presenters are so simple that they can probably paint themselves too quickly to be representative. -- chris |
>
> Maybe you are setting the background to the wrong container ? I'd try > setting > the background of /every/ container to a different colour (and one that is > clearly not white), and see what colour got flashed then. If it's still > white > then at least you know you have to look at a deeper level (maybe at the > Windows > level) for a solution. > > I've tried technique (4) on my example -- setting the pluggable > presenters' > colours to deep blue so that flashing should show up more clearly, and it > seems > to work pretty smoothly. But then, those presenters are so simple that > they > can probably paint themselves too quickly to be representative. > Set all of your background colors to black. That is what I have, and I'm using your architecture, except I have an OGL presenter at the bottom instead of a static text field. The flicker is almost gone. I got about 80% (estimating) of the "white duration" to go away, simply by using a BorderLayout in my PresenterPresenter and setting arrangement to #center for the pluggable. I had left this nil, thinking that the pluggable would fit perfectly inside of the container, because they are the same exact size. This didn't happen. I got a 5 to 10 pixel gap on the left and top. This went away when I made the change, and so did much of the flicker (which I don't understand). The remaining flicker is very short and seems to be in either MyPagePresenter (the pluggable) or in the OGL presenter inside of that. I think the flickering is near the bottom of the view hierarchy because the short flicker occurs very late in the switching cycle (from one OGL presenter to the next), after plugging and just before OGL rendering. I will try to make a simple example of this to help find the problem. Shaping |
Shaping wrote:
> Set all of your background colors to black.That is what I have, Oooh! Very Goth... I tried that, and also thought to maximise the test shell, and I could then see a /slight/ (but nonetheless irritating) flicker -- about 1/2 to 1/4 of the black area would flicker white as the plugin changed. On investigation it turned out that I'd missed one of the container views' backgrounds. Specifically (to my example) the container view used by PlugholePageAbstract to hold the two static texts. With that fixed, I'm seeing no flicker at all. (And I'm not using any of the other techniques I mentioned). That suggests that the problem is either that you also have missed one of the container views, or that the flicker is inherent in your OGL component. Or that something else is amiss, but I can't imagine what... -- chris |
> Oooh! Very Goth...
Gothic. > > I tried that, and also thought to maximise the test shell, and I could > then see > a /slight/ (but nonetheless irritating) flicker -- about 1/2 to 1/4 of the > black area would flicker white as the plugin changed. On investigation it > turned out that I'd missed one of the container views' backgrounds. > Specifically (to my example) the container view used by > PlugholePageAbstract to > hold the two static texts. With that fixed, I'm seeing no flicker at all. > (And I'm not using any of the other techniques I mentioned). > > That suggests that the problem is either that you also have missed one of > the > container views, or that the flicker is inherent in your OGL component. > Or > that something else is amiss, but I can't imagine what... > Yes, I too missed one. There are four: container view in shell; presenterHolder (formerly PresenterPresenter); MyPage; and the generic OGL presenter inside of it. All are black now, and the rendering has a mostly solid black background, but there is a narrow horizontal band of white that sometimes flickers. It is one-sixth to one-third the height of the view. It seems to happen when I /rush/ the switching of the pages, but even this doesn't not happen consistently. Sometimes I see the flash only one in ten tries. Overall, it looks very good. I would like to get to the bottom of it, though. Shaping |
Hi Blair.
I've investigated almost every possible cause of the flicker still remaining in the pluggable presenter architecture that Chris and I have been working through. I need to solve this problem. This is what I know: All of my backgrounds are black. The flicker is intermittent and usually occupies a narrow vertical band in the subview. Occasionally, the "band" occupies the whole subview. The problem is not OpenGL vertical synchronization, lack of which is reported to produce a similar problem. I tried sync-ing on two machines with different models of ATI card, and both times failed to eliminate the flicker. I have seen the flicker go away when OpenGL renders to the main window's client area (I've done much of this mode myself, and prefer it, but you have to role everything yourself). I have seen the flicker problem in a subview/subwindow on both Dolphin and in an MFC app involving a dialog with a static subview as the OGL viewport. So my only remaining thought is whether there is a default white background brush registered by the class associated with the static or whatever window is being used by Dolphin as the ContainerView. Any thoughts? Shaping "Shaping" <[hidden email]> wrote in message news:[hidden email]... >> Oooh! Very Goth... > > Gothic. > >> >> I tried that, and also thought to maximise the test shell, and I could >> then see >> a /slight/ (but nonetheless irritating) flicker -- about 1/2 to 1/4 of >> the >> black area would flicker white as the plugin changed. On investigation >> it >> turned out that I'd missed one of the container views' backgrounds. >> Specifically (to my example) the container view used by >> PlugholePageAbstract to >> hold the two static texts. With that fixed, I'm seeing no flicker at >> all. >> (And I'm not using any of the other techniques I mentioned). >> >> That suggests that the problem is either that you also have missed one of >> the >> container views, or that the flicker is inherent in your OGL component. >> Or >> that something else is amiss, but I can't imagine what... >> > > Yes, I too missed one. There are four: container view in shell; > presenterHolder (formerly PresenterPresenter); MyPage; and the generic OGL > presenter inside of it. All are black now, and the rendering has a mostly > solid black background, but there is a narrow horizontal band of white > that sometimes flickers. It is one-sixth to one-third the height of the > view. It seems to happen when I /rush/ the switching of the pages, but > even this doesn't not happen consistently. Sometimes I see the flash only > one in ten tries. Overall, it looks very good. I would like to get to > the bottom of it, though. > > > Shaping > |
"Shaping" <[hidden email]> wrote in message
news:[hidden email]... > Hi Blair. > > I've investigated almost every possible cause of the flicker still > remaining in the pluggable presenter architecture that Chris and I have > been working through. I need to solve this problem. ... >... > So my only remaining thought is whether there is a default white > background brush registered by the class associated with the static or > whatever window is being used by Dolphin as the ContainerView. Any > thoughts? The single DolphinWindow class used for all Dolphin's Views (not the ControlViews of course) does have a background brush to erase to COLOR_WINDOW, however this is usually overridden from the image by the implementation of WM_ERASEBKGND. For a standard view it is used if no background colour is configured for the view (see View>>onEraseRequired: where comments explain this adequately). This would be the implementation inherited by ContainerView. Any view that completely paints its client area (and which does not therefore require erasing) would normally override #onEraseRequired: to suppress the default behaviour by returning 1 or true. An example in the standard image is DoubleBufferedView. I also posted an interesting example to the group recently of how to implement a MultilineTextEdit with a background image and this did the same. You might want to try creating a ContainerView subclass that doesn't erase the background and suppresses the default beavhiour (i.e. override #onEraseRequired: to return true), or just modify ContainerView itself temporarily. You could also try without a class brush by modifying View class>>winClassBrush to return 0. It will probably have undesirable effects in some apps, but might help your investigation. As I say though, this won't be used unless the DefWindowProc is called, and that will only happen if the #onEraseRequired: implementation returns nil/self rather than true/1. Regards Blair |
>> I've investigated almost every possible cause of the flicker still
>> remaining in the pluggable presenter architecture that Chris and I have >> been working through. I need to solve this problem. ... >>... >> So my only remaining thought is whether there is a default white >> background brush registered by the class associated with the static or >> whatever window is being used by Dolphin as the ContainerView. Any >> thoughts? > > The single DolphinWindow class used for all Dolphin's Views (not the > ControlViews of course) does have a background brush to erase to > COLOR_WINDOW, however this is usually overridden from the image by the > implementation of WM_ERASEBKGND. For a standard view it is used if no > background colour is configured for the view (see View>>onEraseRequired: > where comments explain this adequately). This would be the implementation > inherited by ContainerView. Any view that completely paints its client > area (and which does not therefore require erasing) would normally > override #onEraseRequired: to suppress the default behaviour by returning > 1 or true. An example in the standard image is DoubleBufferedView. I also > posted an interesting example to the group recently of how to implement a > MultilineTextEdit with a background image and this did the same. You might > want to try creating a ContainerView subclass that doesn't erase the > background and suppresses the default beavhiour (i.e. override > #onEraseRequired: to return true), or just modify ContainerView itself > temporarily. I tried placing the true-returning #onEraseRequired: in ContainerView. That made the flashing worse, meaning that the whole view was clearly turning white very briefly. > > You could also try without a class brush by modifying View > class>>winClassBrush to return 0. It will probably have undesirable > effects in some apps, but might help your investigation. As I say though, > this won't be used unless the DefWindowProc is called, and that will only > happen if the #onEraseRequired: implementation returns nil/self rather > than true/1. I tried this too, but there was no change. The flashing almost never occurs sometimes. You can go through five or more page changes with no flashing, and then suddenly, there is a narrow band of white, usually 1/8 to 1/4 of the vertical size of the view, near the bottom or top of the view. This doesn't really look like an erase-background issue, because when the background is being erased, it is very clearly and uniformly being erased--you can't miss it. I'm thinking that this must be a GDI aberration/weirdness/bug. I will post to the OpenGL group about this. My only other thought is to use a WinDIB section for rendering, as I did in my VW OGL stuff, in much the same manner as Jun OpenGL does. This approach seems cleaner than the more conventional rendering to the back buffer and then swapping it to window. With the DIBSection you are rendering to the DIB, and then blitting it to the dc. I never had any flicker problems, but I never used a proper Windows window, except at the top level, where I rendered everything with OGL in the client area, often at full-screen... Shaping |
Free forum by Nabble | Edit this page |