Search code examples
performancedelphibitblt

Delphi slow bitblt from very large bitmap


I am creating a component, in which one can design tables with drag&drop.

I managed to write the drag&drop part and the table rendering, but I have a problem.

I use double buffering, to reduce flickering, by drawing to an in-memory bitmap, then bitblt a portion of it to the screen.

Steps:

  1. Draw table to in-memory bitmap (this can be very large, up to the maximum).
  2. partial in-memory bitmap contents on the control canvas.

The problem is, that the larger the in-memory bitmap is, the slower the bitblt operation will be (obviously).

My question is:

  • How to improve the performance of this? I'm interested in alternative solutions too.

Code:

procedure TCustomGraphicScrollControl.Paint;
var 
    x,y: Integer;
begin
  inherited;

  // Rendering is done in the child class. FRender is a 4-bit color depth 
  // in-memory bitmap. 

  if HorzScrollBar.Visible then x := HorzScrollBar.Position else x:=0;
  if VertScrollBar.Visible then y := VertScrollBar.Position else y:=0;

  // We will create a second in-memory bitmap, with the same dimensions as the control
  // and the same color depth as FRender. This way BitBlt will be a little faster, as it won't be needed to do any conversion.

  // bitblt part of the large in-memory bitmap to screen
  BitBlt(
    FCanvas.Handle,
    0,
    0,
    Width,
    Height,
    FRender.Canvas.Handle,
    x,
    y,
    SRCCOPY
  );
end;

Update:

Removed "Triple buffering" and UpdateScrollBars from code and question.


Solution

    1. Draw table to in-memory bitmap (this can be very large, up to the maximum).
    2. Blit partial in-memory bitmap contents on the control canvas.

    The problem is, that the larger the in-memory bitmap is, the slower the bitblt operation will be (obviously).

    I don't believe that you have correctly diagnosed the problem. The performance of the blit will be largely determined by the size of the target rectangle. It is true that for a very large source bitmap, memory access may be less efficient. But once the source bitmap is large enough to make each scanline read by the blit reside in a different cache line, then the performance should be constant with target rectangle size.

    So, the obvious conclusion to draw from this is that if the performance degrades as the full in-memory bitmap size is increased, then the drawing of that in-memory bitmap is bottleneck. You included no details of that so we cannot offer detailed optimisation suggestions. But your next step is to try to work out where the performance bottleneck really is. If as I believe, the bottleneck is the full in-memory bitmap, then you'll need to find a way to improve performance there.