flat assembler
Message board for the users of flat assembler.
Index
> Windows > How to do flicker free drawing? Goto page 1, 2 Next |
Author |
|
LocoDelAssembly 15 Sep 2008, 22:38
I'm having this problem since my days with MASM, I'm attaching my code now so you can confirm that there is flickering and also to see if I followed the well known article incorrectly. I'm copying from another off-screen bitmap with two levels of indirection intentionally just to show that even creating a fresh compatible bitmap at the time of painting doesn't help neither...
Without resorting to DDraw, is it possible to have real flicker free? Unfortunately I don't have my MASM sources anymore to check but as far as I can recall doing windowed flicker free DDraw was possible. (Although I would like confirmation of this I'm still wanting to avoid DirectX) To see what the program draws keep pressed the left button of your mouse over the window's title bar, that will freeze the application and you'll see the bars that are from top to bottom of the same color rather that two or three. You will also see the real colors of the bars but that is a problem with the human eye and monitor's capability to change a pixel from one color to another fully, but the horizontal divisions have no explanation from the human perception IMHO, that must be just the effect of writing to the video memory on the middle of the monitor's surface scanning (hence it is not flicker free as I expected).
|
|||||||||||
15 Sep 2008, 22:38 |
|
bitRAKE 16 Sep 2008, 02:49
Is this any better?
Code: align 16 proc leonardoWindowProc hwnd, uMsg, wParam, lParam local ps:PAINTSTRUCT, hdc: DWORD, hdcMem: DWORD, hbmMem: DWORD, hOld: DWORD, rect:RECT, buff[64]:BYTE mov eax, [uMsg] cmp eax,WM_ERASEBKGND je .WM_ERASEBKGND cmp eax, WM_DESTROY je .WM_DESTROY leave jmp dword [DefWindowProc] .WM_ERASEBKGND: invoke BitBlt,[wParam], 0,0,WINDOW_WIDTH-64,WINDOW_HEIGHT-64,\ [backBufferDC],0,0,SRCCOPY mov [rect.left], WINDOW_WIDTH-64-64 mov [rect.top], 0 mov [rect.right], WINDOW_WIDTH-64 mov [rect.bottom], WINDOW_HEIGHT-64 invoke BitBlt,[backBufferDC], 0, 0,WINDOW_WIDTH-64-64,WINDOW_HEIGHT-64,\ [backBufferDC],64, 0,SRCCOPY add [color], $201030 and [color], $ffffff invoke CreateSolidBrush,[color] push eax invoke FillRect,[backBufferDC],addr rect,eax pop eax invoke DeleteObject,eax invoke GetTickCount lea edx, [eax-1000] cmp [fpsTime], edx jg .noprint mov edx, eax sub edx, [fpsTime] mov [fpsTime], eax cinvoke wsprintf, addr buff, "%d FPS", [fCount] invoke SetWindowText, [hwnd], addr buff mov [fCount], 0 .noprint: inc [fCount] mov eax,1 ; handled jmp .exit .WM_DESTROY: invoke PostQuitMessage, 0 jmp .processed .processed: xor eax, eax .exit: ret endp (WM_PAINT handler is not required - windows is already painting and we can use her DC.) Your code is actually tripple-buffering and it still flickers very bad on Win2k3. (48 FPS) Edit: Oh, must change last param to force redraw of background: "invoke InvalidateRect,esi,0,TRUE". _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup Last edited by bitRAKE on 16 Sep 2008, 03:03; edited 1 time in total |
|||
16 Sep 2008, 02:49 |
|
LocoDelAssembly 16 Sep 2008, 03:01
bitRAKE, not sure if it is better or not, what I see is a change in the flickering pattern but I'm not sure if it flicks less or not, only that it is somewhat different. (I have also changed the call to InvalidateRect passing TRUE instead of FALSE because it wasn't painting anything without that change).
I get 63 FPS with my code and 64 FPS with your code (because of the change you made on the counting code?). Thanks for answering, testing and the code |
|||
16 Sep 2008, 03:01 |
|
bitRAKE 16 Sep 2008, 03:16
LocoDelAssembly wrote: I get 63 FPS with my code and 64 FPS with your code (because of the change you made on the counting code?). Did you notice this line: Code: invoke BitBlt,[backBufferDC], 0, 0,WINDOW_WIDTH-64-64,WINDOW_HEIGHT-64,\ [backBufferDC],64, 0,SRCCOPY _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
16 Sep 2008, 03:16 |
|
LocoDelAssembly 16 Sep 2008, 03:51
Too much? Try removing the following block of code and you will get around 300 FPS
Code: invoke GetTickCount cmp [time], eax je .getMessage mov [time], eax I use that BitBlt as a simple "scroller" effect. And 300 FPS is a lot far of what I would like to see, 85 FPS, the refresh rate of my monitor. [edit]Aaaahh, the "WINDOW_WIDTH-64-64" part, sorry, I though my code had that too but seems that I removed one "-64" in some of my tests [/edit] |
|||
16 Sep 2008, 03:51 |
|
LocoDelAssembly 16 Sep 2008, 04:03
BTW, how do you know it does much less FPS?
|
|||
16 Sep 2008, 04:03 |
|
bitRAKE 16 Sep 2008, 04:04
LocoDelAssembly wrote: Too much? Chris Hobbs has an example (ESF, bottom of page), but can't figure out what is different from your code. Looks like you are doing everything "correctly". _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
16 Sep 2008, 04:04 |
|
bitRAKE 16 Sep 2008, 04:07
LocoDelAssembly wrote: BTW, how do you know it does much less FPS? _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
16 Sep 2008, 04:07 |
|
revolution 16 Sep 2008, 04:18
To completely eliminate all flicker you have only one option that will work 100% of the time.
Make at least two frame buffers and switch to the next frame during the vertical sync pulse. All other methods will fail in one way or other no matter how hard you try to fix them. If you are really lucky your TickCount will synchronise with the vertical retrace and you won't see any flicker, but this sort of lucky perfect timing is very unlikely. |
|||
16 Sep 2008, 04:18 |
|
LocoDelAssembly 16 Sep 2008, 04:34
Quote:
His animation has an important advantage over mine, he only changes a very small area between frames so perhaps the text in fact flicks but it is too small to be perceived. Yet, I will look the code or better yet, I'll modify his animation with my code to be completely sure that I'm doing the same thing. revolution, but that requires DDraw, right? |
|||
16 Sep 2008, 04:34 |
|
revolution 16 Sep 2008, 05:11
You will need some way to track the vertical retrace. Older systems (before PCs) could use a trick where the program always draws behind the beam position and achieve no flicker but in a modern OS with multitasking this is not possible to do reliably on many different machines with one code base.
If DDraw[1] can allow you to track the vertical retrace then you could try drawing either ahead of or behind the scan beam without using double buffering but I think it would be very very tricky to get right on all systems. [1]I've not got any experience with DDraw so I am assuming you can ask it about the vertical/horizontal beam position. Is this correct? |
|||
16 Sep 2008, 05:11 |
|
LocoDelAssembly 16 Sep 2008, 14:22
Quote:
It has a function that allows you to wait for the vertical black, it is called WaitForVerticalBlank. Then you can do a page flip, a fast blit or draw directly but page flipping is the best if it is available, the second alternative is fast blitting the back buffer to the screen buffer. But I would like to avoid DDraw because it is a pain already porting my GDI code to xlib, but porting DDraw will be even worst and how much longer Microsoft will support DDraw? In Windows Vista seems to be very deprecated and the haven't released any new DirectDraw version, DirectX 7 was the last update, then Direct 8 and 9 has DirectDraw 7 again. Well, maybe I will have to surrender and use DDraw... But what I'm doing will run windowed ALWAYS so I'm not so sure that this is a real viable way. Also, I think that the GDI behavior is more coherent between different computers than DDraw but I hope to be wrong at this one and that I can use it safely on all computers starting with Win98. Anyway, I'll try a little more with GDI, I have to port to fasm the link bitRAKE provided to confirm that my code already do it "the right way". Cheers |
|||
16 Sep 2008, 14:22 |
|
f0dder 16 Sep 2008, 16:15
LocoDelAssembly: the trend for both OpenGL and DirectX is to use 3D acceleration even for 2D code. I'm not sure if I agree with this, as using the 2D routines are usually somewhat easier (and the hardware is going to use the same circuitry anyway), but it does seem to be the route to follow. I wouldn't do it for GUIs though, as I'm not a fan of custom GUIs in most cases.
As for WaitForVerticalBlank(), iirc the flip method has a flag that specifies the same - I'd rather use that than WFVB and then flip. Is flip supported in windowed mode, though? I have a nagging suspicion it isn't. But it's been some years since I touched DX code last. |
|||
16 Sep 2008, 16:15 |
|
LocoDelAssembly 16 Sep 2008, 17:27
Quote:
I think it is not, in that case you would need FastBlt(). Of couse FastBlt() is careless about any window that could be on top of your own so you have to handle clipping also (Don't remember how but I think DDraw had some means for clipping without having to do it yourself, however I would like to see what happens if you have on top a window that has a more complex region than a simple rectangle, even a RoundRect region would be problematic). |
|||
16 Sep 2008, 17:27 |
|
LocoDelAssembly 16 Sep 2008, 21:01
OK, after some troubles (see Compiler Internals), I ported the code (except for the about dialog).
As I suspected, it also flicks... The only change I made is this: Code: .data color dd 0 . . . ;================================== ; Make the call to create a ; green brush for the demo box ;================================== ;::::::::: MODIFIED PART :::::::::: ; RGB 0,192,0 add [color], $201030 and [color], $ffffff mov eax, [color] ;:::::::::::::::::::::::::::::::::: INVOKE CreateSolidBrush, EAX What remains is making a DDraw version of my code and see if by miracle it looks exactly the same even when using WFVB or even page flipping in full-screen mode (my lost MASM code was full-screen DDraw that painted the whole screen with a single color at each frame and more slowly because of course the program was limited by one frame per screen refresh and I remember there was no flick like in the code attached so I find hard to believe that this could be not flickering but human eye perception of fast color changes ). Well, I think that I'll have to live with the flickering
|
|||||||||||
16 Sep 2008, 21:01 |
|
LocoDelAssembly 16 Sep 2008, 23:47
I have just installed and tried Winamp with visualizations and the Advanced Visualization Studio (vis_avs.dll) plug-in, and it flickers as hell even in full-screen mode, however, the other visualization modules don't flicker at all (but by the things you can set looks like some are using Direct3D). Perhaps the flicker is nVidia fault? Anyone here tried with non nVidia cards?
The Nullsoft Tiny Fullscreen v2.09 (vis_nsfs.dll) plug-in doesn't flicker neither but I don't know what is using to render to screen but the Milkdrop ones uses 3D acceleration for sure. |
|||
16 Sep 2008, 23:47 |
|
bitRAKE 17 Sep 2008, 01:20
What I find odd is that windows is trying to update with screen refresh - this is obvious from the limited FPS - and it is not working as it should. Seems obvious that something is incorrect. My first thought was that windows delays the BitBlt, but the source changes which forces early BitBlt.
Edit: I just changed my video card and it looks much better - from tearing in top and bottom ot just tearing at the bottom. FPS is at 65 with a refresh of 60 or 75. At 60hz the tearing will cycle, but it's sycronized at 75hz. _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup Last edited by bitRAKE on 17 Sep 2008, 02:05; edited 1 time in total |
|||
17 Sep 2008, 01:20 |
|
LocoDelAssembly 17 Sep 2008, 02:04
Do you mean Winamp or some of the programs of this thread?
|
|||
17 Sep 2008, 02:04 |
|
bitRAKE 17 Sep 2008, 02:12
I'm still working with the original code.
The only reason ESF flickers is the background color of the window overwriting the colored regions and this occurs in the "non-flickering" mode as the numbers update - it still flickers. Your FASM version flickers of course. _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
17 Sep 2008, 02:12 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.