flat assembler
Message board for the users of flat assembler.

Index > Windows > How to do flicker free drawing?

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
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).


Description:
Download
Filename: test_draw.zip
Filesize: 3.22 KB
Downloaded: 248 Time(s)

Post 15 Sep 2008, 22:38
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 16 Sep 2008, 02:06
Weird, when I've tried it on my brother's computer there was no flicking and the FPS was 63 also. However, I'm not sure whether it is Vista that implements the flicker free painting or the LCD display makes the flicking imperceptible.

I have also tested it on an Athlon 750 MHz with Windows Server 2003 and a CRT monitor and the flicking was even more noticeable (because seems that GetTickCount has more resolution on this SO so the FPS have risen to 99).
Post 16 Sep 2008, 02:06
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
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    
I still get flicker, but this performs much better (53 FPS).
(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
Post 16 Sep 2008, 02:49
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
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 Smile
Post 16 Sep 2008, 03:01
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
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?).
It really does much less.

Did you notice this line:
Code:
invoke  BitBlt,[backBufferDC], 0, 0,WINDOW_WIDTH-64-64,WINDOW_HEIGHT-64,\ 
               [backBufferDC],64, 0,SRCCOPY    
...your code copies too much?

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 16 Sep 2008, 03:16
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
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
    
(It is located on the message processing loop)
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 Razz[/edit]
Post 16 Sep 2008, 03:51
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 16 Sep 2008, 04:03
BTW, how do you know it does much less FPS?
Post 16 Sep 2008, 04:03
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 16 Sep 2008, 04:04
LocoDelAssembly wrote:
Too much?
You copy the portion which gets overwritten by the Fill. No matter, it is not the source of the problem. Yeah, hitting 580 FPS, lol.

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
Post 16 Sep 2008, 04:04
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 16 Sep 2008, 04:07
LocoDelAssembly wrote:
BTW, how do you know it does much less FPS?
Eh, I meant less work - not less FPS. The WM_ERASEBKGND (double buffering) handler requires much less processing time verses WM_PAINT (tripple buffering). Sorry, for the confusion.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 16 Sep 2008, 04:07
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20404
Location: In your JS exploiting you and your system
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.
Post 16 Sep 2008, 04:18
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 16 Sep 2008, 04:34
Quote:

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".


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?
Post 16 Sep 2008, 04:34
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20404
Location: In your JS exploiting you and your system
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?
Post 16 Sep 2008, 05:11
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 16 Sep 2008, 14:22
Quote:

[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?

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
Post 16 Sep 2008, 14:22
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
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.
Post 16 Sep 2008, 16:15
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 16 Sep 2008, 17:27
Quote:

Is flip supported in windowed mode, though?

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).
Post 16 Sep 2008, 17:27
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
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 Confused).

Well, I think that I'll have to live with the flickering Sad


Description:
Download
Filename: esf_modified.zip
Filesize: 10.48 KB
Downloaded: 169 Time(s)

Post 16 Sep 2008, 21:01
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
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.
Post 16 Sep 2008, 23:47
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
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. Question

_________________
¯\(°_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
Post 17 Sep 2008, 01:20
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 17 Sep 2008, 02:04
Do you mean Winamp or some of the programs of this thread?
Post 17 Sep 2008, 02:04
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
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
Post 17 Sep 2008, 02:12
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.