Sign in Join

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

Mailing lists / lazarus / 2010-05

Fastest way to draw

14 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

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

Brad Campbell

G'day guys,

I'm experimenting with an Oscilloscope at the moment. I'm using a TImage on a form, and I'm writing using Image.Canvas.Pen / Image.Canvas.Line.

Each refresh consists of

Image.Canvas.Clear()
Repeat 20 -> Image.Canvas.Line(draw graticule)
Repeat Width -> Image.Canvas.Line(draw CH1 sample) Repeat Width -> Image.Canvas.Line(draw CH2 sample)

So there are _lots_ of little fiddly bits to draw (about 1200 line segments per refresh).

There has to be a faster way to get data to the screen in a cross-platform fashion (I'm developing on Linux but ultimately I'll be compiled for OSX and Win32).

Has anyone done anything similar?

Regards,
Brad

Dolphins are so intelligent that within a few weeks they can train Americans to stand at the edge of the pool and throw them fish.

Reply by email

Mattias Gaertner
to Brad Campbell
Show quoted text 16 lines
G'day guys, I'm experimenting with an Oscilloscope at the moment. I'm using a TImage on a form, and I'm writing using Image.Canvas.Pen / Image.Canvas.Line. Each refresh consists of Image.Canvas.Clear() Repeat 20 -> Image.Canvas.Line(draw graticule) Repeat Width -> Image.Canvas.Line(draw CH1 sample) Repeat Width -> Image.Canvas.Line(draw CH2 sample) So there are _lots_ of little fiddly bits to draw (about 1200 line segments per refresh). There has to be a faster way to get data to the screen in a cross-platform fashion (I'm developing on Linux but ultimately I'll be compiled for OSX and Win32).

Paint onto a memory image and then draw that.

As memory image you can use TBitmap which has comfortable fonts, but is not the fastest.

Or you can use fpcanvas (it comes with fpc). See here http://wiki.lazarus.freepascal.org/Developing_with_Graphics#Drawing_without_LCL You can tune it quite a lot.

If you use lazarus 0.9.29 you can use aggpas. The package can be found in lazarus/components/aggpas. For examples in
components/aggpas/lazarus/example/AggPasInLCLDemo1.lpi. Aggpas is completely written in pascal, quite fast and the results are the same on all platforms (as always: fonts are a problem).

And finally you can use opengl - for example via the TOpenglControl.

Has anyone done anything similar?

No. You are the first.

Mattias

Reply by email

Brad Campbell
to Mattias Gaertner
Mattias Gaertner wrote 14 lines
As memory image you can use TBitmap which has comfortable fonts, but is not the fastest. Or you can use fpcanvas (it comes with fpc). See here http://wiki.lazarus.freepascal.org/Developing_with_Graphics#Drawing_without_LCL You can tune it quite a lot. If you use lazarus 0.9.29 you can use aggpas. The package can be found in lazarus/components/aggpas. For examples in components/aggpas/lazarus/example/AggPasInLCLDemo1.lpi. Aggpas is completely written in pascal, quite fast and the results are the same on all platforms (as always: fonts are a problem). And finally you can use opengl - for example via the TOpenglControl.

Cheers for all that Mattias. I appreciate then leads. aggpas looks really cool. I'll get it benchmarked against my current stuff in the next day or so.

> Has anyone done anything similar? No. You are the first.

Righto, I'll be sure to post my code when I've got it fast enough then.

Regards,
Brad

Dolphins are so intelligent that within a few weeks they can train Americans to stand at the edge of the pool and throw them fish.

Reply by email

Duncan Parsons
to Brad Campbell

From: Brad Campbell [mailto:]
Sent: 21 May 2010 15:38

Show quoted text 6 lines
Mattias Gaertner wrote: > As memory image you can use TBitmap which has comfortable fonts, but > is not the fastest. > > Or you can use fpcanvas (it comes with fpc). See here >

http://wiki.lazarus.freepascal.org/Developing_with_Graphics#Drawing_wi

> thout_LCL > You can tune it quite a lot. > > If you use lazarus 0.9.29 you can use aggpas. The package can be

found

> in lazarus/components/aggpas. For examples in > components/aggpas/lazarus/example/AggPasInLCLDemo1.lpi. > Aggpas is completely written in pascal, quite fast and the results

are

Show quoted text 5 lines
> the same on all platforms (as always: fonts are a problem). > > And finally you can use opengl - for example via the TOpenglControl. Cheers for all that Mattias. I appreciate then leads. aggpas looks

really cool. I'll get it

Show quoted text 10 lines
benchmarked against my current stuff in the next day or so. >> Has anyone done anything similar? > > No. You are the first. Righto, I'll be sure to post my code when I've got it fast enough then. Regards, Brad

There's GR32 as well, which now has FPC/Laz compatibility. http://www.graphics32.org/

Overall, the best way to do that sort of thing is to have a bitmap in memory (either loaded from a file, or drawn on application start) then when doing what's needed copy/draw the background, then draw the additional lines. I've done this sort of thing in realtime in audio/VST programming, sometimes using Peter Morris's DIB controls, and sometimes GR32. AggPas has come on since I last tried it a few years ago, and could also be a good choice as suggested.

:-)

DSP

Reply by email

Hans-Peter Diettrich
to Brad Campbell: I'm experimenting with an Oscilloscope at the moment. I'm using a TImage on a form, and…
I'm experimenting with an Oscilloscope at the moment. I'm using a TImage on a form, and I'm writing using Image.Canvas.Pen / Image.Canvas.Line.
Has anyone done anything similar?

I did it on Win32, using the ScrollWindow procedure. Dunno whether other platforms/widgetsets offer similar functionality.

You can do it "manually", by blitting the retained part of the image to its new position in the bitmap, add the new frame, and display the updated bitmap.

DoDi

Reply by email

Felipe Monteiro de Carvalho
to Brad Campbell: I'm experimenting with an Oscilloscope at the moment. I'm using a TImage on a form, and…

Hello,

Brad Campbell wrote
I'm experimenting with an Oscilloscope at the moment.

Are you implementing the hardware too?

Show quoted text 6 lines
So there are _lots_ of little fiddly bits to draw (about 1200 line segments per refresh). There has to be a faster way to get data to the screen in a cross-platform fashion (I'm developing on Linux but ultimately I'll be compiled for OSX and Win32).

In my 2nd year of university my group built built an osciloscope with a GUI written in Lazarus and the hardware being an ISA Board .

For my project the following technique was more then enough:

http://wiki.lazarus.freepascal.org/Developing_with_Graphics#Create_a_custom_control_which_draws_itself

But as others have pointer, there are other solutions.

I think the download link is this one, but the server is down now: http://eletronicalivre.iv.org.br/portal/portugues/osciloscopio/download

Felipe Monteiro de Carvalho

Reply by email

Brad Campbell
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote 6 lines
Hello, On Fri, May 21, 2010 at 3:30 PM, Brad Campbell wrote: > I'm experimenting with an Oscilloscope at the moment. Are you implementing the hardware too?

Just the firmware. I'm using the Parallax PropScope. 25M samples/sec. 2 Channels of 10 bit and 4 bits of Logic input.

http://www.parallax.com/Store/Microcontrollers/PropellerTools/tabid/143/ProductID/586/List/0/Default.aspx?SortField=ProductName,ProductName

Show quoted text 9 lines
> So there are _lots_ of little fiddly bits to draw (about 1200 line segments > per refresh). > > There has to be a faster way to get data to the screen in a cross-platform > fashion (I'm developing on Linux but ultimately I'll be compiled for OSX and > Win32). In my 2nd year of university my group built built an osciloscope with a GUI written in Lazarus and the hardware being an ISA Board .

This is a USB device with an FTDI converter built in. I've managed nice comms at about 960k baud and I've implemented the comms in another thread to get around polling and other issues. I can get the packets in _far_ faster than I can draw them currently.

I want to refresh the display 30-40 times a second to keep up with the possible sweep rates, at the moment I can manage between 4 & 10 depending on the number of samples I'm taking per sweep. At 500 samples/sweep at the moment I'm sampling over 3 times faster than I can draw. At 6000 samples / sweep I can draw a the same rate I sample (~4Hz).

When I get the drawing code fast enough I'll post a solution. I've just ordered a nice slow PPC Mac to experiment with, which should make it much easier to benchmark drawing speed.

Brad

Dolphins are so intelligent that within a few weeks they can train Americans to stand at the edge of the pool and throw them fish.

Reply by email

Brad Campbell
to Duncan Parsons: From: Brad Campbell [mailto:] Sent: 21 May 2010 15:38…
Duncan Parsons wrote 10 lines
There's GR32 as well, which now has FPC/Laz compatibility. http://www.graphics32.org/ Overall, the best way to do that sort of thing is to have a bitmap in memory (either loaded from a file, or drawn on application start) then when doing what's needed copy/draw the background, then draw the additional lines. I've done this sort of thing in realtime in audio/VST programming, sometimes using Peter Morris's DIB controls, and sometimes GR32. AggPas has come on since I last tried it a few years ago, and could also be a good choice as suggested.
Just as a follow up. Rendering to a 1600x1200 screen, timing was along these lines;

TImage.Canvas : 200ms / frame

Clear / draw all lines

AggLCLCanvas : 90ms / frame

Clear / draw all lines / copy to TImage

AggLCLCanvas was taking 30ms just to do a clear. Using a filled rectangle with the desired background colour took only 10ms by comparison.

RGBBitmap32 : 19ms / frame

Clear / draw all lines / render to TPanel.Canvas (and update in onpaint event as required).

For the simple stuff I'm doing (no text and just lines) LazRGBGraphics goes like a bat out of hell.

I tried using fpimage and an fpcanvas but nothing I tried could render them to any visual component (Not that I tried very hard after trying LazRGBGraphics - it's *fast*)

AggPas was pretty quick, and if I needed the additional fruit it'd probably be a great choice, but for just slapping lines down on a canvas LazRGBGraphics is hard to beat.

Regards,
Brad.

Dolphins are so intelligent that within a few weeks they can train Americans to stand at the edge of the pool and throw them fish.

Reply by email

Reimar Grabowski
to Brad Campbell
Show quoted text 6 lines
TImage.Canvas : 200ms / frame AggLCLCanvas : 90ms / frame AggLCLCanvas was taking 30ms just to do a clear. Using a filled rectangle with the desired background colour took only 10ms by comparison.

Did you report this bug?

RGBBitmap32 : 19ms / frame but for just slapping lines down on a canvas LazRGBGraphics is hard to beat.

I'd like to give it a try. 19ms does not sound that fast. Definitly missing the magical 60fps. How many lines did you draw for this tests? And did you only measure the time for drawing/rendering or the time for a whole frame update?

:R:

A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing? A: Top-posting. Q: What is the most annoying thing in e-mail?

Reply by email

Paul Breneman
to Brad Campbell: Just the firmware. I'm using the Parallax PropScope. 25M samples/sec. 2 Channels of 10…

Hi Brad,

...

Just the firmware. I'm using the Parallax PropScope. 25M samples/sec. 2 Channels of 10 bit and 4 bits of Logic input. http://www.parallax.com/Store/Microcontrollers/PropellerTools/tabid/143/ProductID/586/List/0/Default.aspx?SortField=ProductName,ProductName

...

Show quoted text 14 lines
This is a USB device with an FTDI converter built in. I've managed nice comms at about 960k baud and I've implemented the comms in another thread to get around polling and other issues. I can get the packets in _far_ faster than I can draw them currently. I want to refresh the display 30-40 times a second to keep up with the possible sweep rates, at the moment I can manage between 4 & 10 depending on the number of samples I'm taking per sweep. At 500 samples/sweep at the moment I'm sampling over 3 times faster than I can draw. At 6000 samples / sweep I can draw a the same rate I sample (~4Hz). When I get the drawing code fast enough I'll post a solution. I've just ordered a nice slow PPC Mac to experiment with, which should make it much easier to benchmark drawing speed.

This sounds like a very neat project. I hope we can keep in touch as what you are doing may tie into this educational project that I'd also like to tie into the Parallax educational offerings: http://www.turbocontrol.com/monitor.htm

Regards, Paul Breneman www.dbReplication.com - VCL database replication components www.TurboControl.com - Hardware and software development services - Educational programming project for environment monitoring - Information on using FreePascal for embedded systems - Support information for the TurboPower open source libraries

Reply by email

Brad Campbell
to Reimar Grabowski: On Sat, 22 May 2010 19:28:20 +0800 Did you report this bug? I'd like to give it a try.…
Reimar Grabowski wrote
> AggLCLCanvas was taking 30ms just to do a clear. Using a filled rectangle with the desired > background colour took only 10ms by comparison. Did you report this bug?

Not yet, no. I need time to prepare some solid test cases.

Show quoted text 6 lines
> RGBBitmap32 : 19ms / frame > but > for just slapping lines down on a canvas LazRGBGraphics is hard to beat. I'd like to give it a try. 19ms does not sound that fast. Definitly missing the magical 60fps. How many lines did you draw for this tests? And did you only measure the time for drawing/rendering or the time for a whole frame update?

Uh, about 4000 lines, and the time was from "receive a packet of bytes" to after the "application.processmessages" that ensured the display was properly rendered.

The pre-processing of the array was usually less than 1ms, so the rendering is what takes the time. The drawing is pretty fast (usually ~1.5ms).

When I can only get 45fps from the Scope hardware, I'm really not fussed about not being able to draw 60.

What is magical about 60fps?

Regards,
Brad

Dolphins are so intelligent that within a few weeks they can train Americans to stand at the edge of the pool and throw them fish.

Reply by email

Brad Campbell
to Mattias Gaertner: On Fri, 21 May 2010 21:30:45 +0800 Paint onto a memory image and then draw that. As…
Mattias Gaertner wrote 9 lines
> > There has to be a faster way to get data to the screen in a cross-platform fashion (I'm developing > on Linux but ultimately I'll be compiled for OSX and Win32). Paint onto a memory image and then draw that. As memory image you can use TBitmap which has comfortable fonts, but is not the fastest.

So, taking into account your comment "is not the fastest" I thought I'd give a plain TBitmap a try. It's by _far_ the fastest I've tried yet. So fast in fact that I really can't time it using Millisecondsbetween(). Amazing.

I have 2 TBitmaps assigned globally. One I pre-prepare with my background (stuff, graticule and other lines) every time there is a resize.

In the OnPaint() handler I copy the contents of the background TBitmap to the foreground TBitmap, then draw a couple of thousand lines on it before copying it to the canvas of a panel (I'm using a TPanel as the display component) using Panel.Canvas.Copy() to copy the canvas from the foreground bitmap. I can't believe how fast it is.

Best of all, it requires no new components or packages :)

Regards,
Brad

Dolphins are so intelligent that within a few weeks they can train Americans to stand at the edge of the pool and throw them fish.

Reply by email

Mattias Gaertner
to Brad Campbell
Show quoted text 14 lines
Mattias Gaertner wrote: >> >> There has to be a faster way to get data to the screen in a cross-platform fashion (I'm developing >> on Linux but ultimately I'll be compiled for OSX and Win32). > > Paint onto a memory image and then draw that. > > As memory image you can use TBitmap which has comfortable fonts, but > is not the fastest. > So, taking into account your comment "is not the fastest" I thought I'd give a plain TBitmap a try. It's by _far_ the fastest I've tried yet. So fast in fact that I really can't time it using Millisecondsbetween(). Amazing.

Indeed.
Can you provide the benchmark source?

Show quoted text 9 lines
I have 2 TBitmaps assigned globally. One I pre-prepare with my background (stuff, graticule and other lines) every time there is a resize. In the OnPaint() handler I copy the contents of the background TBitmap to the foreground TBitmap, then draw a couple of thousand lines on it before copying it to the canvas of a panel (I'm using a TPanel as the display component) using Panel.Canvas.Copy() to copy the canvas from the foreground bitmap. I can't believe how fast it is. Best of all, it requires no new components or packages :)

:)

Mattias

Reply by email

Duncan Parsons
to Brad Campbell: So, taking into account your comment "is not the fastest" I thought I'd give a plain…

Oh, that's good to hear - I'll bare it in mind next time I'm doing similar things. I've generally used other libs as I've needed alpha blending of images, but you tend to forget the easy things when you've had more challenging requirements!

[apologies for topposting!]
DSP

Earlier message 42 lines
-----Original Message----- From: Brad Campbell [mailto:] Sent: 23 May 2010 11:47 To: Lazarus mailing list Subject: Re: [Lazarus] Fastest way to draw Mattias Gaertner wrote: >> >> There has to be a faster way to get data to the screen in a >> cross-platform fashion (I'm developing on Linux but ultimately I'll be compiled for OSX and Win32). > > Paint onto a memory image and then draw that. > > As memory image you can use TBitmap which has comfortable fonts, but > is not the fastest. > So, taking into account your comment "is not the fastest" I thought I'd give a plain TBitmap a try. It's by _far_ the fastest I've tried yet. So fast in fact that I really can't time it using Millisecondsbetween(). Amazing. I have 2 TBitmaps assigned globally. One I pre-prepare with my background (stuff, graticule and other lines) every time there is a resize. In the OnPaint() handler I copy the contents of the background TBitmap to the foreground TBitmap, then draw a couple of thousand lines on it before copying it to the canvas of a panel (I'm using a TPanel as the display component) using Panel.Canvas.Copy() to copy the canvas from the foreground bitmap. I can't believe how fast it is. Best of all, it requires no new components or packages :) Regards, Brad -- Dolphins are so intelligent that within a few weeks they can train Americans to stand at the edge of the pool and throw them fish. --

Reply by email