I have a windows desktop application where I am seeing jitters while scrolling. The WM_PAINT call is being handled failry fast 10ms.
-The WM_PAINT call is being forced using RedrawWindow after handling WM_MOUSEWHEEL so effectively I am drawing in the same cycle synchronously. Could this be a cause of problem by messing with dispatcher? Should I just invalidateRect and handle the paint in the WM_PAINT call. The answer I am looking for is how can I make scroll butter smooth something like chrome, so what should be the right strategy for scrolling.
-Should I draw a large viewPort and scroll on visible area using ScrollWindow and do all the invalidation offscreen, does this strategy work ?
Related
I'm trying to make a borderless window where the maximized window properly fits the work area of the screen when maximized. This has turned out to be more difficult than I could've ever imagined, and every solution I can find has some sort of downside or glitch that prevents it from being perfect. Some of the glitches are very minor and probably wouldn't be a big deal to most people, but it bothers me.
I know it's possible to do this somehow because I've used a few programs that clearly draw their own non-client area but have proper maximize behavior and appear to be without glitches. Steam and Twitch clients are two examples. However, I have no idea how much code or what sort of tricks they used to get their windows to have that behavior.
Background Info:
When maximizing a window, the window manager positions the window in such a way that the non-client area falls just outside of the visible work area so that the non-client area is not visible when the window is maximized. I remove the non-client area by returning 0 from WM_NCCALCSIZE because I want to be able to draw my own non-client area. The result is that the window manager is trying to account for a non-client area that doesn't exist and my maximized borderless window extends off the screen approximately 7 or 8 pixels in all directions.
What I've tried to fix this:
I've tried handling WM_MINMAXINFO, which doesn't work because the window manager ignores any dimensions passed unless they are smaller than the work area or monitor area. For example, if I subtract 1 from the ptMaxSize.x coordinate, the window fits almost perfectly except there's a 1 pixel transparent space where you can click whatever is behind the window. See this post for more info.
What almost works:
I found this post which contains a solution that almost works perfectly, except that when maximizing the window with Aero Snap, there's a very brief flicker where you can see everything behind the window. This doesn't occur when maximizing the window by double clicking the title bar or using the maximize buttons, even when adjusting the size of the non-client area on maximize. Here's a video that demonstrates the issue.
Video explanation:
First, I maximize the window several times with Aero Snap without the adjustments being made to the non-client area to demonstrate that the maximize transition is flicker-free. Then I show that the window flickers after having adjusted the size of the non-client area on maximizing.
My Question:
Is there a way to prevent the flicker from happening when using this method to fit the maximized borderless window to the work area? Or is there a better way to go about making the maximized window fit the screen? Handling WM_MINMAXINFO seemed like the best hack-free approach, but because of the quirky way windows responds to dimensions that are greater than or equal to the work area, it doesn't seem to work.
I'm making a 2d tile level editor (you click a tile on the loaded spritesheet and then can draw it to the main area). Although it performs fine on desktop the mobile performance is staggeringly slow, so I've been testing out various perf tweaks. Monitoring the results with framerate monitor from chrome dev tools (desktop), I noticed something I don't understand. When I click on the menu icon and the overlay menu pops out (visible on the left in the screenshot, uses css transform:translate for the animation) the frame rate skyrockets up to about the monitor refresh sync rate, even when drawing the canvas.
If I haven't touched the menu icon, the framrate is about 40fps on idle and ~15fps when drawing the canvas, but simply triggering the menu animation eliminates the framerate drop. It also seems to have a lasting effect, the idle framerate of 40fps no longer drops on repaints when the menu is closed, and when the menu is open the framerate stays up near 60fps.
So the question is twofold: why does triggering this css animation have such a HUGE effect on canvas drawing perf (15fps vs 60), and is there any way to force a consistent 60fps without having the menu open all the time?
PS* The visibility of the menu is irrelevant, leaving it on the page makes no difference but animating it in seems to affect the framerate greatly. The menu has the 'null transform hack' applied because it was triggering a repaint of the canvas it overlays, but removing only drops the fps a little at each stage of the process, the relative performance of the different states of the program are similar.
Chrome has this thing where upon using a css transformation it enables hardware acceleration.
It would be easy to verify it by moving the menu position with js instead of using css tranformation.
Regarding the second part of the question, if that's the case, a hidden or off-screen transformation should have the same effect.
I have a custom NSView that draws (with -drawRect) a graph. It also tracks the mouse position (with -mouseMoved and the like) and draws the cursor position/coordinates relative to the axes.
The graph is big and (potentially) slow to draw, and doesn't depend on the mouse position. The mouse-over effect is tiny, and always fast to draw. I don't want to have to redraw everything when the mouse moves a couple pixels, because it feels sluggish.
I'm sure I can make my own private graphics context (doubled in size, if on a 2x display), draw the chart data into that once, and then have -drawRect simply blit that into the view's drawing context. Alternatively, I could split my NSView subclass into two classes, and have one just the chart data, and one just the overlay, and place them exactly on top of each other (though they have to share a bit of data, so this seems awkward).
Is there a built-in method to make this easier, or is there a more idiomatic way of handling this?
Take a look at these NSWindow methods:
Bracketing Drawing Operations
– cacheImageInRect:
– restoreCachedImage
– discardCachedImage
Normally, with a view, you define a drawRect: method that draws contents on-demand. You can, however, do on the spot drawing in a view as result of events for example, by locking focus on the view, performing the drawing, then unlocking focus. The missing link in this on-the-spot drawing, is somehow undoing it without calling your potentially heavy drawRect: via setNeedsDisplay:
This is where the Bracketed drawing operations on NSWindow come into play. Before locking focus on the view and doing some on-the-spot drawing, cache an image of the view in the area you intend to draw. When you next want to update your drawing (while tracking events, perhaps) then restore the cached image, rinse, and repeat.
I have code that paints to a hidden canvas style="visibility: hidden" and then plots this hidden canvas onto one that is visible on screen.
Now as far as I understand, with the hidden canvas drawing should be performant even if it is not triggered via requestAnimationFrame. Is this so? Because I would then only use requestAnimationFrame for the blitting of the hidden canvas on the main screen.
The app I'm working on is not heavily animated but has quite a lot of lines to draw when something changes.
You should create the canvas with document.createElement("canvas") and don't attach this created canvas in any DOM container instead of use a hidden style . (Needs tests to prove, but at least is another way to create a back buffer canvas).
Even so, in my experience I never see effective gains by using backbuffered canvas with requestAnimationFrame. In fact, requestAnimationFrame does their job of synchronize the browser paint with the monitor's refresh rate and this enables smooth animations and more responsive pages. Also the animation will stop if the user switches to another tab which saves CPU usage and battery life of mobile devices.
I would not recommend the use of a back buffer canvas and I suggest, instead, that you perform your drawing stuff directly in main canvas inside a requestAnimationFrame callback. If you continuously keep drawing into the backbuffer canvas and trapped the main canvas into a requestAnimationFrame call you might unnecessarily(or not, that depends on you) lose some frames generating waste of CPU usage and low quality animations.
To help choose the better approach always do your own performance tests for your specific use cases.
And requestAnimationFrame is no needed at all. You are always able to use setInterval or setTimeout but the pros of using requestAnimationFrame are way bigger than his cons what make it the better approach for animations.
Using a double-buffered screen with the Simple DirectMedia Layer, is it more efficient to call SDL_UpdateRect once after blitting multiple images or to call it once after blitting each individual image before calling SDL_Flip? In other words, will SDL_UpdateRect cause the screen to be updated immediately, or does it simply tell the Simple DirectMedia Layer which areas must be updated when the screen is flipped? How should it typically be used with a double-buffered screen?
For reference, here is the description of SDL_UpdateRect.
Makes sure the given area is updated on the given screen. The
rectangle must be confined within the screen boundaries (no clipping
is done).
If 'x', 'y', 'w' and 'h' are all 0, SDL_UpdateRect will update the
entire screen.
Yes, SDL_UpdateRect update screen (or rect) immediately.
No need to use the SDL_UpdateRect and SDL_Flip jointly, they do the same things but different ways.
The difference is that SDL_UpdateRect can update only part of the screen (and work by copying pixels from your surface to screen), and SDL_Flip refresh the entire screen (and works by flip buffers).
So, if you use double-buffered screen no need to call SDL_UpdateRect, just call SDL_Flip after all blits.
http://www.libsdl.org/docs/html/sdlsetvideomode.html
Calling SDL_Flip will flip the buffers and update the screen. All
drawing will take place on the surface that is not displayed at the
moment. If double buffering could not be enabled then SDL_Flip will
just perform a SDL_UpdateRect on the entire screen.
And don't forget that double buffering works only with SDL_HWSURFACE and SDL_FULLSCREEN video mode.