LCL-CustomDrawn: Implements a new much faster image copying based in TLazIntfImage.GetDataLineStart. Speeds the magnifier drawing from 630ms to 477ms in X11

git-svn-id: trunk@36576 -
This commit is contained in:
sekelsenmat 2012-04-05 12:22:56 +00:00
parent 620a57d289
commit 51262ce4b0
5 changed files with 88 additions and 19 deletions

View File

@ -246,6 +246,7 @@ type
ScreenBitmapHeight: Integer; ScreenBitmapHeight: Integer;
ScreenBitmapWidth: Integer; ScreenBitmapWidth: Integer;
ScreenImage: TLazIntfImage; ScreenImage: TLazIntfImage;
ScreenFormat: TLazCanvasImageFormat;
// Android Activity callbacks // Android Activity callbacks
ActivityOnCreate: TProcedure; ActivityOnCreate: TProcedure;

View File

@ -104,6 +104,9 @@ begin
FTerminating := False; FTerminating := False;
DefaultFontSize := 10; DefaultFontSize := 10;
// To be resistent against backend issues
CDWidgetset.ScreenFormat := clfARGB32;
{$ifndef CD_UseNativeText} {$ifndef CD_UseNativeText}
FFontPaths:= TStringList.Create; FFontPaths:= TStringList.Create;
FFontList := THashedStringList.Create; FFontList := THashedStringList.Create;

View File

@ -185,6 +185,9 @@ begin
ScreenInfo.PixelsPerInchY:= 96; ScreenInfo.PixelsPerInchY:= 96;
ScreenInfo.Initialized:= True; ScreenInfo.Initialized:= True;
// ToDo: Actually check which format it is at
ScreenFormat := clfBGR24;
//if (not (woX11SkipWMHints in WindowOptions)) and (woWindow in WindowOptions) then //if (not (woX11SkipWMHints in WindowOptions)) and (woWindow in WindowOptions) then
//begin //begin
LeaderWindow := XCreateSimpleWindow(FDisplay, XDefaultRootWindow(FDisplay), 0, 0, 1, 1, 0, 0, 0); LeaderWindow := XCreateSimpleWindow(FDisplay, XDefaultRootWindow(FDisplay), 0, 0, 1, 1, 0, 0, 0);

View File

@ -23,11 +23,6 @@ uses
InterfaceBase, LCLIntf; InterfaceBase, LCLIntf;
type type
TUpdateLazImageFormat = (
clfRGB16_R5G6B5,
clfRGB24, clfRGB24UpsideDown, clfBGR24,
clfBGRA32, clfRGBA32, clfARGB32);
{ TCDBaseControl } { TCDBaseControl }
TCDBaseControl = class TCDBaseControl = class
@ -139,7 +134,7 @@ function FindTopMostVisibleForm: TCDNonNativeForm;
// Routines for non-native wincontrol // Routines for non-native wincontrol
procedure UpdateControlLazImageAndCanvas(var AImage: TLazIntfImage; procedure UpdateControlLazImageAndCanvas(var AImage: TLazIntfImage;
var ACanvas: TLazCanvas; AWidth, AHeight: Integer; AFormat: TUpdateLazImageFormat; var ACanvas: TLazCanvas; AWidth, AHeight: Integer; AFormat: TLazCanvasImageFormat;
AData: Pointer = nil; AForceUpdate: Boolean = False; AData: Pointer = nil; AForceUpdate: Boolean = False;
AFreeImageOnUpdate: Boolean = True; ADataOwner: Boolean = True); AFreeImageOnUpdate: Boolean = True; ADataOwner: Boolean = True);
procedure DrawFormBackground(var AImage: TLazIntfImage; var ACanvas: TLazCanvas); procedure DrawFormBackground(var AImage: TLazIntfImage; var ACanvas: TLazCanvas);
@ -184,6 +179,8 @@ procedure FontsScanDir(APath: string; var AFontPaths: TStringList; var AFontList
implementation implementation
uses customdrawnint;
var var
// List with the Z-order of non-native forms, index=0 is the bottom-most form // List with the Z-order of non-native forms, index=0 is the bottom-most form
NonNativeForms: TFPList = nil; NonNativeForms: TFPList = nil;
@ -353,7 +350,7 @@ end;
// If AForceUpdate=True then it will update even if the width and height remain the same // If AForceUpdate=True then it will update even if the width and height remain the same
procedure UpdateControlLazImageAndCanvas(var AImage: TLazIntfImage; procedure UpdateControlLazImageAndCanvas(var AImage: TLazIntfImage;
var ACanvas: TLazCanvas; AWidth, AHeight: Integer; AFormat: TUpdateLazImageFormat; var ACanvas: TLazCanvas; AWidth, AHeight: Integer; AFormat: TLazCanvasImageFormat;
AData: Pointer = nil; AForceUpdate: Boolean = False; AData: Pointer = nil; AForceUpdate: Boolean = False;
AFreeImageOnUpdate: Boolean = True; ADataOwner: Boolean = True); AFreeImageOnUpdate: Boolean = True; ADataOwner: Boolean = True);
var var
@ -409,6 +406,7 @@ begin
if (ACanvas <> nil) then ACanvas.Free; if (ACanvas <> nil) then ACanvas.Free;
ACanvas := TLazCanvas.Create(AImage); ACanvas := TLazCanvas.Create(AImage);
ACanvas.ImageFormat := AFormat;
end; end;
{$IFDEF VerboseCDLazCanvas} {$IFDEF VerboseCDLazCanvas}
DebugLn(Format(':<[UpdateControlLazImageAndCanvas] Output Image: %x Canvas: %x', DebugLn(Format(':<[UpdateControlLazImageAndCanvas] Output Image: %x Canvas: %x',
@ -950,7 +948,7 @@ end;
procedure TCDWinControl.UpdateImageAndCanvas; procedure TCDWinControl.UpdateImageAndCanvas;
begin begin
UpdateControlLazImageAndCanvas(ControlImage, ControlCanvas, UpdateControlLazImageAndCanvas(ControlImage, ControlCanvas,
WinControl.Width, WinControl.Height, clfARGB32); WinControl.Width, WinControl.Height, {$ifdef CD_Support_Alpha_Controls}clfARGB32{$else}CDWidgetset.ScreenFormat{$endif});
end; end;
function TCDWinControl.IsControlBackgroundVisible: Boolean; function TCDWinControl.IsControlBackgroundVisible: Boolean;

View File

@ -33,7 +33,9 @@
unit lazcanvas; unit lazcanvas;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
{.$define lazcanvas_debug} { $define lazcanvas_debug}
{ $define lazcanvas_profiling}
{ $define lazcanvas_new_fast_copy}
interface interface
@ -42,12 +44,24 @@ uses
Classes, SysUtils, contnrs, Math, Classes, SysUtils, contnrs, Math,
// FCL-Image // FCL-Image
fpimgcanv, fpcanvas, fpimage, clipping, pixtools, fppixlcanv, fpimgcanv, fpcanvas, fpimage, clipping, pixtools, fppixlcanv,
{$ifdef lazcanvas_new_fast_copy}
intfgraphics, // remove if fclimage gets RawPixel
{$endif}
// regions // regions
lazregions lazregions
{$ifdef lazcanvas_debug}, LCLProc{$endif}; {$if defined(lazcanvas_debug) or defined(lazcanvas_profiling)}
, lazutf8sysutils, LCLProc
{$endif}
;
type type
TLazCanvasImageFormat = (
clfOther,
clfRGB16_R5G6B5,
clfRGB24, clfRGB24UpsideDown, clfBGR24,
clfBGRA32, clfRGBA32, clfARGB32);
{ TFPSharpInterpolation } { TFPSharpInterpolation }
// This does a very sharp and square interpolation for stretching, // This does a very sharp and square interpolation for stretching,
@ -102,6 +116,7 @@ type
HasNoImage: Boolean; HasNoImage: Boolean;
NativeDC: PtrInt; // Utilized by LCL-CustomDrawn NativeDC: PtrInt; // Utilized by LCL-CustomDrawn
ExtraFontData: TObject; // Utilized by LCL-CustomDrawn ExtraFontData: TObject; // Utilized by LCL-CustomDrawn
ImageFormat: TLazCanvasImageFormat;
constructor create (AnImage : TFPCustomImage); constructor create (AnImage : TFPCustomImage);
destructor destroy; override; destructor destroy; override;
procedure SetLazClipRegion(ARegion: TLazRegion); procedure SetLazClipRegion(ARegion: TLazRegion);
@ -595,31 +610,80 @@ procedure TLazCanvas.CanvasCopyRect(ASource: TLazCanvas; const ADestX, ADestY,
ASourceX, ASourceY, ASourceWidth, ASourceHeight: Integer); ASourceX, ASourceY, ASourceWidth, ASourceHeight: Integer);
var var
x, y, CurDestX, CurDestY, CurSrcX, CurSrcY: Integer; x, y, CurDestX, CurDestY, CurSrcX, CurSrcY: Integer;
lx, ly: Integer;
lDrawWidth, lDrawHeight: Integer; lDrawWidth, lDrawHeight: Integer;
lColor: TFPColor; lColor: TFPColor;
{$IFDEF lazcanvas_profiling}
lTimeStart: TDateTime;
{$ENDIF}
lScanlineSrc, lScanlineDest: PByte;
begin begin
{$IFDEF lazcanvas_profiling}
lTimeStart := NowUTC();
{$ENDIF}
// Take care not to draw outside the source and also not outside the destination area // Take care not to draw outside the source and also not outside the destination area
lDrawWidth := Min(Self.Width - ADestX, ASource.Width - ASourceX); lDrawWidth := Min(Self.Width - ADestX, ASource.Width - ASourceX);
lDrawHeight := Min(Self.Height - ADestY, ASource.Height - ASourceY); lDrawHeight := Min(Self.Height - ADestY, ASource.Height - ASourceY);
lDrawWidth := Min(lDrawWidth, ASourceWidth); lDrawWidth := Min(lDrawWidth, ASourceWidth);
lDrawHeight := Min(lDrawHeight, ASourceHeight); lDrawHeight := Min(lDrawHeight, ASourceHeight);
for y := 0 to lDrawHeight - 1 do {$ifdef lazcanvas_new_fast_copy}
// If the formats match, make a fast copy of the data itself, without pixel conversion
if (Image is TLazIntfImage) and (ASource.Image is TLazIntfImage) and
(ImageFormat in [clfRGB24, clfRGB24UpsideDown, clfBGR24, clfBGRA32, clfRGBA32, clfARGB32]) and
(ImageFormat = ASource.ImageFormat) then
begin begin
for x := 0 to lDrawWidth - 1 do for y := 0 to lDrawHeight - 1 do
begin begin
CurDestX := ADestX + x; CurDestY := ADestY + y + FWindowOrg.Y;
CurDestY := ADestY + y; if CurDestY >= Height then Continue;
CurSrcX := ASourceX + x;
CurSrcY := ASourceY + y; CurSrcY := ASourceY + y;
// Never draw outside the destination lScanlineSrc := TLazIntfImage(ASource.Image).GetDataLineStart(CurSrcY);
if (CurDestX < 0) or (CurDestY < 0) then Continue; lScanlineDest := TLazIntfImage(Image).GetDataLineStart(CurDestY);
Inc(lScanlineSrc, (ASourceX)*3);
Inc(lScanlineDest, (ADestX + FWindowOrg.X)*3);
lColor := ASource.Colors[CurSrcX, CurSrcY]; for x := 0 to lDrawWidth -1 do
Self.Colors[CurDestX, CurDestY] := lColor; begin
lScanlineDest^ := lScanlineSrc^;
Inc(lScanlineSrc, 1);
Inc(lScanlineDest, 1);
lScanlineDest^ := lScanlineSrc^;
Inc(lScanlineSrc, 1);
Inc(lScanlineDest, 1);
lScanlineDest^ := lScanlineSrc^;
Inc(lScanlineSrc, 1);
Inc(lScanlineDest, 1);
end;
end;
end
// General case of copying
else
{$endif}
begin
for y := 0 to lDrawHeight - 1 do
begin
for x := 0 to lDrawWidth - 1 do
begin
CurDestX := ADestX + x;
CurDestY := ADestY + y;
CurSrcX := ASourceX + x;
CurSrcY := ASourceY + y;
// Never draw outside the destination
if (CurDestX < 0) or (CurDestY < 0) then Continue;
lColor := ASource.Colors[CurSrcX, CurSrcY];
Self.Colors[CurDestX, CurDestY] := lColor;
end;
end; end;
end; end;
{$IFDEF lazcanvas_profiling}
DebugLn(Format('[TLazCanvas.CanvasCopyRect] Paint duration: %d ms', [DateTimeToTimeStamp(NowUTC() - lTimeStart).Time]));
{$ENDIF}
end; end;
{$if defined(ver2_4) or defined(ver2_5)} {$if defined(ver2_4) or defined(ver2_5)}