Recent

Author Topic: Repainting 60hz with LCL (or: Application.ProcessMessages drops clicks!)  (Read 2282 times)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9867
  • Debugger - SynEdit - and more
    • wiki
Re: Repainting 60hz with LCL (or: Application.ProcessMessages drops clicks!)
« Reply #15 on: January 24, 2020, 05:49:44 am »
The close button seems related to showModal.
modal runs a 2nd separate event loop. That seems to somehow be more affected by the heavy amount of timer events. Probably because of the 1st event loop gets plenty to do.


Even if I put the painting in DrawGameWorld into  a loop (so nothing else runs in between, no wait for the timer, no screen update, just paint to the bitmap.canvas) => I get 30 to 40 frames a second (depending on where the objects are). Core I7 8700K at 4.7 GHZ.
That is just drawing to the bitmap. This did not include drawing the bitmap to the screen.
So the real numbers will be less.


There are some game building libs for Lazarus. They use stuff like opengl. That may be a bit faster.

Superdisk

  • Jr. Member
  • **
  • Posts: 73
Re: Repainting 60hz with LCL (or: Application.ProcessMessages drops clicks!)
« Reply #16 on: January 24, 2020, 05:57:43 am »
30/40 FPS as it's running the drawing code in a 10x loop actually isn't too bad. The performance I get out of BGRABitmap and LineTo isn't bad either, so I'm not really looking for techniques to speed up the drawing.

My only issue is the ShowModal thing. Any ideas what could be causing it? (Or potentially any functions to call as a hack to make it work?)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9867
  • Debugger - SynEdit - and more
    • wiki
Re: Repainting 60hz with LCL (or: Application.ProcessMessages drops clicks!)
« Reply #17 on: January 24, 2020, 06:05:43 am »
30/40 FPS as it's running the drawing code in a 10x loop actually isn't too bad. The performance I get out of BGRABitmap and LineTo isn't bad either, so I'm not really looking for techniques to speed up the drawing.

Ah, yes, I didn't even see that you already had a 10 loop. I packed that same loop into a 100 loop. So 1000 times to the bitmap took 2.5 to 3.2 secs. That is good.
I didnt test the bitmap to screen. But that should be fine too.



Not tested, but what may be faster...
Instead of
TempOutput.Canvas.Ellipse

Create this once as an image to its own bitmap (once for each color). At app start.

Then just copy bitblt the small image to each target location on the bigger image.


--
If I run the drawing without your 10 loop, the close button works.
but that depends on the cpu, and system load. Mine just cleared the queue fast enough in that case.

Handoko

  • Hero Member
  • *****
  • Posts: 5153
  • My goal: build my own game engine using Lazarus
Re: Repainting 60hz with LCL (or: Application.ProcessMessages drops clicks!)
« Reply #18 on: January 24, 2020, 06:08:41 am »
My only issue is the ShowModal thing. Any ideas what could be causing it? (Or potentially any functions to call as a hack to make it work?)

From your previous example, I saw the TPaintBox was constantly changing and updating after a modal form showing up.

Maybe you can consider to stop (or pause) the TPainBox changing. Capture, save store it to a TBitmap and show only the bitmap on the Paint event if a modal form poping up? It sounds a bit difficult but I believe you can do it.
« Last Edit: January 24, 2020, 06:13:06 am by Handoko »

Superdisk

  • Jr. Member
  • **
  • Posts: 73
Re: Repainting 60hz with LCL (or: Application.ProcessMessages drops clicks!)
« Reply #19 on: January 24, 2020, 06:31:39 am »
Quote
Maybe you can consider to stop (or pause) the TPainBox changing. Capture, save store it to a TBitmap and show only the bitmap on the Paint event if a modal form poping up? It sounds a bit difficult but I believe you can do it.

I considered doing that, but in this particular program I kinda want to allow the paintbox to continue updating in the background. I might implement this as a temporary workaround.

Anyway, I cracked open TCustomForm.ShowModal and it is this:
Code: Pascal  [Select][+][-]
  1. repeat
  2.   { Delphi calls Application.HandleMessage
  3.         But HandleMessage processes all pending events and then calls idle,
  4.         which will wait for new messages. Under Win32 there is always a next
  5.         message, so it works there. The LCL is OS independent, and so it uses
  6.         a better way: }
  7.   try
  8.         WidgetSet.AppProcessMessages; // process all events
  9.   except
  10.         if Application.CaptureExceptions then
  11.           Application.HandleException(Self)
  12.         else
  13.           raise;
  14.   end;
  15.   if Application.Terminated then
  16.         ModalResult := mrCancel;
  17.   if ModalResult <> 0 then
  18.   begin
  19.         CloseModal;
  20.         if ModalResult<>0 then break;
  21.   end;
  22.  
  23.   Application.Idle(true);
  24. until False;

I put in a little debugging code and noticed that it calls WidgetSet.AppProcessMessages and never returns from that call. So I guess that's the issue. Is there some way to only process 1 message or something?

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: Repainting 60hz with LCL (or: Application.ProcessMessages drops clicks!)
« Reply #20 on: January 24, 2020, 07:49:31 am »
Dunno about Linux, but on Windows Invalidate method uses InvalidateRect procedure, that should queue WM_PAINT, instead of sending it immediately. Therefore ProcessMessages shouldn't be needed, as WM_PAINT is processed only when there are no other messages in queue. Only problem - WM_PAINT can take long to process, that makes UI irresponsive. In this case you can use thread to process painting. Just don't forget to use Canvas.Lock and Canvas.Unlock.

My old application, that uses massive GIF animation, works just perfectly.
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

 

TinyPortal © 2005-2018