Silverfrost Forums

Welcome to our forums

Fastest way to colour pixels in a %pl?

2 Oct 2025 1:29 #32383

In the program below, a heat map is plotted by colouring pixels within the “PLOT_ADJUST” section of a %pl call back.

This task is performed using to nested loops to work across/down the pixel space.

When the program is run a %ls box appears on the RHS of the graphic. This allows you to change whether the individual pixels are coloured using a call to DRAW_POINT@(ix,iy,iz) or DRAW_FILLED_RECTANGLE@(ix,iy,ix,iy,iz)

Intuitively I would expect a call to DRAW_POINT@ to be faster than DRAW_FILLED_RECTANGLE@(ix,iy,ix,iy,iz) to set the colour of an individual pixel at ix, iy, to colour iz (as there are fewer arguments to process).

However, as this example demonstrates (on my machines), the nested do loops that call DRAW_FILLED_RECTANGLE@ execute 3 to 4 times faster than those with calls to DRAW_POINT@. Apart from these alternative draw calls, the nested do loops are identical.

I am unable to explain this significant difference. Can anybody can shed some light on this? I’m at a loss with this one.

https://www.dropbox.com/scl/fi/elkhsu5jxjmxeqsyu0fru/ex35_drawpoint_or_filledrect.f95?rlkey=ninbyykqqvar6dtc6zlqu0fiq&st=k9xdyi55&dl=0

2 Oct 2025 2:12 #32384

I have a vague recollection that draw_point@ can be extremely slow. I don't remember if it related specifically to the use of smoothing.

The primitive function called without smoothing is SetPixel. The primitive functions called for smoothing are GdipBitmapSetPixel and GdipDrawImageRectI.

So a rectangle is used anyway for GDI+ and this could mean that a 'set pixel' function was not available or did not work.

See https://learn.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-graphics-flat.

2 Oct 2025 6:35 #32385

Paul,

Thanks, that is very useful.

Your recollection is entirely consistent with what I have observed both without and with smoothing.

I will use draw_filled_rectangle@ instead of draw_pixel@ from now on.

According to AI:

*When you call draw_point@ in ClearWin+ (which wraps Windows SetPixel), each pixel goes through a full GDI pipeline individually:

  1. GDI checks the device context (DC) for clipping, mapping modes, and transformations.
  2. GDI validates the coordinates to make sure they are inside the drawable region.
  3. GDI computes the actual memory location of the pixel in the framebuffer or bitmap.
  4. The pixel value is written, sometimes with extra synchronization to ensure the graphics engine sees it immediately.
  5. Windows may flush the pipeline to the display (or schedule a refresh). All of these steps are repeated for every single pixel, which is why SetPixel is notoriously slow — even for just one pixel, a lot of overhead happens.

On the other hand, when you call draw_filled_rectangle@ (even for a rectangle of size 1×1):

  1. ClearWin+ translates it into a GDI fill command (like FillRect or Rectangle).
  2. The GDI fill routines are highly optimised: they can batch memory writes, skip redundant calculations, and often operate directly on internal framebuffer buffers.
  3. The Windows graphics engine has special “fast paths” for rectangle fills, even for tiny rectangles. This means the memory and clipping calculations are done efficiently in one go rather than per pixel.
  4. Finally, the GDI engine can push the block to the screen efficiently, rather than flushing per pixel.

So the irony is that drawing a “tiny box” with draw_filled_rectangle@ triggers the optimized batch path, while draw_point@ forces a slow, per-pixel pipeline traversal.

draw_point@ = slow path, per-pixel, unbatched, lots of overhead.

draw_filled_rectangle@ = fast path, batch-optimized, even if the rectangle is just one pixel.

This explains why, counterintuitively, plotting a single “pixel rectangle” can be faster than plotting a single point. *

3 Oct 2025 7:20 #32386

Ken

There may be some mileage in using %gr[user_surface].

I don't understand how the AI engine has managed to compose it's response to your question. I suppose it's a bit like what you read in newspapers. It relates something approximating to the truth - sometimes quite accurately, sometimes not. In this case I am both impressed and perplexed.

3 Oct 2025 2:26 #32387

Fascinating. Does draw_filled_polygon@ work faster than pixel by pixel?

3 Oct 2025 9:17 #32389

and how about DRAW_LINE_between@(ix1,iy1,ix2,iy2,icolor) formerly DRAW_LINE@ ?

Please login to reply.