Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / customdrawn / 2012-04

New fast bitmap copying

15 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Felipe Monteiro de Carvalho

Hello,

http://svn.freepascal.org/cgi-bin/viewvc.cgi?view=rev&root=lazarus&revision=36576

This commit starts speeding up image drawing. The magnifier full painting went from 630ms to 477ms for me.

ToDos:

1>Give up on speed improvements if there is a non-ractangular clip region 2>Consider the clip region
3>Implement for 16 and 32 bpp too, is now only for 24 bpp (like our X11 implementation is)
4>Consider if we are not getting out of the destination size in the X axis

Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho
to Felipe Monteiro de Carvalho
Vincent Snijders wrote
Why not replace for x := 0 to lDrawWidth -1 do by move(lScanlineSrc^, lScanlineDest^, 3 * lDrawWidth);

Good idea! Implemented in rev36578 and it even saved around 15ms

In the same revision also implemented these ToDos:

3>Implement support for 32 bpp too
4>Consider if we are not getting out of the destination size in the X axis

Felipe Monteiro de Carvalho
Giuliano Colla
to Felipe Monteiro de Carvalho

Il 05/04/2012 15:04, Felipe Monteiro de Carvalho ha scritto:

Show quoted text 13 lines
On Thu, Apr 5, 2012 at 2:49 PM, Vincent Snijders wrote: > Why not replace > for x := 0 to lDrawWidth -1 do > by > move(lScanlineSrc^, lScanlineDest^, 3 * lDrawWidth); Good idea! Implemented in rev36578 and it even saved around 15ms In the same revision also implemented these ToDos: 3>Implement support for 32 bpp too 4>Consider if we are not getting out of the destination size in the X axis

ASAP I'll test it, because on my X11 platform VMG paint time is (before patches) 1103-1143 ms, plus 115-115 ms of X drawing time!

Felipe Monteiro de Carvalho
to Felipe Monteiro de Carvalho: On Thu, Apr 5, 2012 at 2:49 PM, Vincent Snijders Good idea! Implemented in rev36578 and…

And the speed increases don't stop =) Rev 36580 made a massive improvement over rectangle filling when filling an entire object. The fullscreen X11 form drawing went from 95ms to 33ms to me.

I also activated the new fast image copying by default.

I could feel quite a lot the speed implement of the rectangle feeling in Android.

Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho
to Giuliano Colla: Il 05/04/2012 15:04, Felipe Monteiro de Carvalho ha scritto: ASAP I'll test it, because…
Giuliano Colla wrote
ASAP I'll test it, because on my X11 platform VMG paint time is (before patches) 1103-1143 ms, plus 115-115 ms of X drawing time!

Here with the magnifier without graphical border (the default is with graphical border) I am getting:

X11 event WM_PAINT - Window 48234498, Delay 6 ms
[TCDWSCustomForm.DrawRawImageToGC] Paint duration: 60 ms [TCDWSCustomForm.EvPaint] Total Paint duration: 359 ms of this CustomDrawn: 359 ms Native: 0
X11 event WM_PAINT - Window 48234498, Delay 0 ms
[TCDWSCustomForm.DrawRawImageToGC] Paint duration: 62 ms [TCDWSCustomForm.EvPaint] Total Paint duration: 5 ms of this CustomDrawn: 5 ms Native: 0
X11 event WM_PAINT - Window 48234498, Delay 0 ms
[TCDWSCustomForm.DrawRawImageToGC] Paint duration: 61 ms

But it still should be faster to be fluent. Right now I think I can get something like 3 FPS. I think it needs at least 6 FPS. I never calculated the FPS in LCL-Win32, but it surely is very big.

I do have 1 more idea to speed the drawing: Use LCL stretching instead of the magnifier stretching. I added a non-LCL stretching to the magnifier due to issues with non-LCL-Win32 stretching, but now I can implement stretching as it should be in LCL-CustomDrawn and using it directly should make things faster.

Felipe Monteiro de Carvalho
Giuliano Colla
to Felipe Monteiro de Carvalho: And the speed increases don't stop =) Rev 36580 made a massive improvement over rectangle…

Il 05/04/2012 17:14, Felipe Monteiro de Carvalho ha scritto:

Show quoted text 9 lines
And the speed increases don't stop =) Rev 36580 made a massive improvement over rectangle filling when filling an entire object. The fullscreen X11 form drawing went from 95ms to 33ms to me. I also activated the new fast image copying by default. I could feel quite a lot the speed implement of the rectangle feeling in Android.

I'm afraid that something has broken in the process. Both my test program and canvastest from the examples now crash when attempting to take a screenshot.

Actually the crash occurs when attempting to assign the grabbed image to a bitmap:

screenshotunit line 46:
imgScreenshot.Picture.Bitmap.Assign(bmp)

In customdrawnlclintf.inc, line 508,
System.Move(lBmpRawImage.Data^, NewData^, lBmpRawImage.DataSize);

lBmpRawImage.Data is a null pointer, and therefore the move causes a SIGSEV. As you've been playing with that part of code, maybe you can fix it faster than I can do, painfully trying to reconstruct what you were thinking

Felipe Monteiro de Carvalho
to Giuliano Colla
Giuliano Colla wrote
I'm afraid that something has broken in the process. Both my test program and canvastest from the examples now crash when attempting to take a screenshot.

Indeed. Funny that the magnifier works fine in all platforms.

Show quoted text 6 lines
In customdrawnlclintf.inc, line 508, System.Move(lBmpRawImage.Data^, NewData^, lBmpRawImage.DataSize); lBmpRawImage.Data is a null pointer, and therefore the move causes a SIGSEV. As you've been playing with that part of code, maybe you can fix it faster than I can do, painfully trying to reconstruct what you were thinking

I did not change anything there, it probably just points to an error somewhere else. How can DataSize be > 0 and Data=nil at the same time? Something generated this wrong state.

Felipe Monteiro de Carvalho
Giuliano Colla
to Felipe Monteiro de Carvalho

Il 06/04/2012 12:01, Felipe Monteiro de Carvalho ha scritto:

It was caused by my first attempt at implementing Mask support. Fixed in rev 36598

Now both canvas test and VMG do work!

Drawing time in VMG has been reduced from 1.1 seconds to around 640/650 ms in my platform:

[TCDWSCustomForm.EvPaint] Total Paint duration: 638 ms of this CustomDrawn: 638 ms Native: 0 CD_X11 event WM_PAINT - Window 46137346, Delay 0 ms [TCDWSCustomForm.DrawRawImageToGC] Paint duration: 115 ms

Two things to mention:

VMG shows an enormous amount of such warnings

WARNING: TLazIntfImage.ChooseRawBitsProc Unsupported BitsPerPixel=0

1628 such messages in a less than 30 seconds test. With other programs you get just three or four such warnings at startup, and that's all.
Does this mean something one has to worry about?

In my platform (Fedora 14, Desktop either KDE or XFC4, no difference) with Customdrawn when you click the VMG window is minimized, but the Icon doesn't appear in the SysTray. Where to look?

Felipe Monteiro de Carvalho
to Giuliano Colla
Giuliano Colla wrote 7 lines
VMG shows an enormous amount of such warnings WARNING: TLazIntfImage.ChooseRawBitsProc Unsupported BitsPerPixel=0 1628 such messages in a less than 30 seconds test. With other programs you get just three or four such warnings at startup, and that's all. Does this mean something one has to worry about?

Not so much to worry, but those warnings point to something unimplemented and we need to implement what is missing (I'm not sure what, actually) to get it to shut up, because surely it is slowing us down and is very annoying.

In my platform (Fedora 14, Desktop either KDE or XFC4, no difference) with Customdrawn when you click the VMG window is minimized, but the Icon doesn't appear in the SysTray. Where to look?

I added code for systray but it doesn't work, so you should look at customdrawntrayicon_x11.inc and ideally fix it =)

Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho
to Felipe Monteiro de Carvalho

Hello,

I did a big expansion of the region code, so now we could make a push to get LazEyes working =) If you could make code to set the region of a window it would be great =) It is this routine:

function SetWindowRgn(hWnd: HWND; hRgn: HRGN; bRedraw:
Boolean):longint; override;

It will need both a generic and a Backend implementation. HRGN in CustomDrawn is the same thing as a TLazRegion from the unit lcl/lazregions.pas which has a nice description of regions (svn update to get the latest).

LazEyes uses mostly elliptical regions.

regions in LazRegions are defined as either a simple rect region or as a list of parts, being that all parts would be combined with the OR operator.

Felipe Monteiro de Carvalho
Giuliano Colla
to Felipe Monteiro de Carvalho

Il 06/04/2012 14:34, Felipe Monteiro de Carvalho ha scritto:

Show quoted text 20 lines
Hello, I did a big expansion of the region code, so now we could make a push to get LazEyes working =) If you could make code to set the region of a window it would be great =) It is this routine: function SetWindowRgn(hWnd: HWND; hRgn: HRGN; bRedraw: Boolean):longint; override; It will need both a generic and a Backend implementation. HRGN in CustomDrawn is the same thing as a TLazRegion from the unit lcl/lazregions.pas which has a nice description of regions (svn update to get the latest). LazEyes uses mostly elliptical regions. regions in LazRegions are defined as either a simple rect region or as a list of parts, being that all parts would be combined with the OR operator.

Fine. With your previous e-mail and this one you gave me some things to do. Now I must take care of other things (those who pay for my meals ;-) ), but there's a long week-end waiting for us... So I just tagged the e-mails as unread, and they'll pop up again when I look. I have also some other ideas on areas of general speed improvement, but they can wait.

Felipe Monteiro de Carvalho
to Giuliano Colla

Hello,

I added a new option to disable the form background manually as requested in the forum, and so I used it and also changed the magnifier code to draw in the form OnPaint event instead of inside a sub-control. The result was a massive speed gain:

[TCDWSCustomForm.DrawRawImageToGC] Paint duration: 61 ms [TCDWSCustomForm.EvPaint] Total Paint duration: 185 ms of this CustomDrawn: 185 ms Native: 0
X11 event WM_PAINT - Window 85983234, Delay 1 ms

The speed was gained mostly by drawing to the canvas directly instead of first to the bitmap.

But using LCL-Gtk2 now the drawing is lightning fast. I didn't measure it, but it is extremely fast! Probably 20 to 30 FPS... so we have some catch up to do =D

I think that reusing the X native image should be something to think of. In Android I commited a patch which I received to reuse the native bitmap and things are getting really fast in Android =) The guy said he is getting 60FPS using LCL-CustomDrawn + Graphics32 in Android!!! =D My little interface is getting more and more traction and adoption.

I always said that there is no secret solution here, just optimize, optimize and optimize and the drawing starts flying.

Anyway I guess that now finally I have a good enough speed to be able to make a Mac OS X release of the VMG with LCL-CustomDrawn =) But first I have to implement native menu and TTrayIcon support in the Cocoa backend ... and also check if the native image can be reused in Mac OS X too.

Felipe Monteiro de Carvalho
Giuliano Colla
to Felipe Monteiro de Carvalho

Felipe Monteiro de Carvalho ha scritto:

Show quoted text 35 lines
Hello, I added a new option to disable the form background manually as requested in the forum, and so I used it and also changed the magnifier code to draw in the form OnPaint event instead of inside a sub-control. The result was a massive speed gain: [TCDWSCustomForm.DrawRawImageToGC] Paint duration: 61 ms [TCDWSCustomForm.EvPaint] Total Paint duration: 185 ms of this CustomDrawn: 185 ms Native: 0 X11 event WM_PAINT - Window 85983234, Delay 1 ms The speed was gained mostly by drawing to the canvas directly instead of first to the bitmap. But using LCL-Gtk2 now the drawing is lightning fast. I didn't measure it, but it is extremely fast! Probably 20 to 30 FPS... so we have some catch up to do =D I think that reusing the X native image should be something to think of. In Android I commited a patch which I received to reuse the native bitmap and things are getting really fast in Android =) The guy said he is getting 60FPS using LCL-CustomDrawn + Graphics32 in Android!!! =D My little interface is getting more and more traction and adoption. I always said that there is no secret solution here, just optimize, optimize and optimize and the drawing starts flying. Anyway I guess that now finally I have a good enough speed to be able to make a Mac OS X release of the VMG with LCL-CustomDrawn =) But first I have to implement native menu and TTrayIcon support in the Cocoa backend ... and also check if the native image can be reused in Mac OS X too.

I'm afraid that in the next two weeks I'll have little or no time at all to devote to Customdrawn, because of last minute tight schedule needs by our customers. As they pay not only for my meals, but also for the facilities I can take advantage of, also in behalf of Customdrawn, they take precedence =)
I just had time for a few cosmetic adjustments (such as getting color depth and image format from X, instead of figuring it out), and I believe I have located what's missing to make TrayIcon to work under X11, but I had no time to fix it. I'd better update from svn before sending patches, but there's not such a hurry. They won't change our life. ;-)

I agree with you that basic optimization is very important. If painting is too slow, nothing else will help. However there's another point which I believe deserves some attention. In the current implementation of Customdrawn, at least as far as X11 is concerned, I've seen a difference with respect to other widgesets.

In other widgesets, all painting occurs when ProcessMessages is executed, i.e. at the end of the main loop. LCL calls the WS methods, which make any required housekeeping, and then queue a message, for the actual painting. This makes a number of optimizations much easier, because at the end of main loop one has all elements in hand, and one can avoid useless or multiple paints.
In Customdrawn painting occurs earlier, and this is IMHO a source of poor performance.
e.g. Changing a widget position means changing both Top and Left property. They're changed with two separate instructions. If there's one paint for Top change, and one for Left change, you paint twice. If you wait the end of Main Loop, both Top and Left are changed, and just one paint is required. And at that level one can paint directly on the native canvas.
In order to implement this behavior, one should create a message queue on Customdrawn, which may require some work, but is much less revolutionary than using different threads, and may turn out very effective, for all backends.

What's your opinion about that?

Giuliano

Giuliano Colla Whenever people agree with me, I always feel I must be wrong (O. Wilde)
Giuliano Colla
to Felipe Monteiro de Carvalho: I added a new option to disable the form background manually as requested in the forum,…

Il 10/04/2012 12:23, Felipe Monteiro de Carvalho ha scritto:

Show quoted text 7 lines
Hello, I added a new option to disable the form background manually as requested in the forum, and so I used it and also changed the magnifier code to draw in the form OnPaint event instead of inside a sub-control. The result was a massive speed gain:

That's very nice, but moving the Types usage declaration in CustomDrawnInt in behalf of Mac, makes a mess in other platforms. In CD_X11 fpc interprets wrongly xlib types, and doesn't compile anymore:

..customdrawnobject_x11.inc(249,56) Error: Incompatible type for arg no. 2: Got "<address of procedure(Pointer,TXPointer,LongInt,LongInt,PXPointer);CDecl>", expected "<procedure variable type of procedure(PDisplay,TXPointer,LongInt,LongInt,PXPointer);CDecl>"

As it's a Mac specific issue, let's handle it for what it is:

// RTL
{$ifndef CD_Cocoa}Types,{$endif}
  at the beginning, and afterwards:
{$ifdef CD_Cocoa} cocoa stuff, Types, {$endif}

That way Types is where it should be for everyone, except for Mac.

Giuliano