在寻找替代 GDI 的替代品时,我试图在 Windows 7中测试 Delphi 的 2010 TDirect2DCanvas性能。
我通过使用 Direct2D 绘制一条巨大的折线对其进行了测试,结果速度非常慢,即使数据量比我使用 GDI 运行相同测试的数据量少 500 倍(我什至没有使用位图作为 GDI 中的后缓冲,我只是直接画到表单画布上)。
所以我猜要么:
a) Direct2D比GDI慢;
b) TDirect2DCanvas 很慢;
c)我做错了什么
,希望是 c)。
我写的测试代码是:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Direct2D, D2D1;
type
TForm2 = class(TForm)
private
{ Private declarations }
FD2DCanvas: TDirect2DCanvas;
FData: array[0..50000] of TPoint;
public
procedure CreateWnd; override;
procedure WMSize(var Message: TWMSize); message WM_SIZE;
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
{ Public declarations }
end;
var
Form2: TForm2;
implementation
uses utils;
{$R *.dfm}
procedure TForm2.CreateWnd;
var
i: Integer;
begin
inherited;
FD2DCanvas := TDirect2DCanvas.Create(Handle);
for i := 0 to High(FData) do begin
FData[i].X := Random(Self.ClientWidth div 2);
FData[i].Y := Random(Self.ClientHeight);
end;
end;
procedure TForm2.WMPaint(var Message: TWMPaint);
var
PaintStruct: TPaintStruct;
begin
BeginPaint(Handle, PaintStruct);
try
FD2DCanvas.BeginDraw;
try
FD2DCanvas.Polyline(FData);
finally
FD2DCanvas.EndDraw;
end;
finally
EndPaint(Handle, PaintStruct);
end;
end;
procedure TForm2.WMSize(var Message: TWMSize);
begin
if Assigned(FD2DCanvas) then begin
ID2D1HwndRenderTarget(FD2DCanvas.RenderTarget).Resize(D2D1SizeU(ClientWidth, ClientHeight));
end;
end;
end.
此外,我真的很愿意在实际代码中绘制长折线,因为我正在开发的系统需要绘制大量约 2500 点的折线(至少 10K 条)。
更新 (2010-11-06)
我之前发现 Direct2D 似乎不喜欢折线,如果您使用大量单线(2 点折线),它会绘制得更快。
多亏了Chris Bensen,我发现在使用 anti-aliasing 时,大型折线的速度很慢。所以我按照 Chris 的建议禁用了抗锯齿,绘制 50k 线的性能从 ~6000ms 到 ~3500ms。
事情仍然可以改进,因为 Direct2D在使用 anti-aliasing 时不能很好地处理折线。禁用抗锯齿功能则相反。
现在用 Direct2D 绘制 50k 线的时间,如果我在没有抗锯齿的情况下绘制大折线,大约是 50 毫秒。不错,嗯!
问题是,如果我绘制位图, GDI 仍然比 Direct2D 快,并且在完成后我 BitBlt 将结果返回到表单,它以 ~35ms的速度绘制,并且具有相同的图形质量。而且,Direct2D 似乎也已经在使用后备缓冲区(它只是在EndDraw()
被调用时绘制)。
那么,这是否可以通过某种方式改进以使使用 Direct2D 在速度方面值得?
这是更新的代码:
type
TArray = array[0..1] of TPoint;
PArray = ^TArray;
procedure TForm2.WMPaint(var Message: TWMPaint);
var
PaintStruct: TPaintStruct;
begin
FD2DCanvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
BeginPaint(Handle, PaintStruct);
try
FD2DCanvas.BeginDraw;
try
FD2DCanvas.Pen.Color := clRed;
FD2DCanvas.Polyline(FData);
finally
FD2DCanvas.EndDraw;
end;
finally
EndPaint(Handle, PaintStruct);
end;
end;
顺便说一句,即使我使用Chris预先创建几何图形的建议,速度也与 GDI 的速度大致相同,但仍然没有更快。
我的电脑正常运行 Direct3D 和 OpenGL 应用程序,这里是 dxDiag 输出:http ://mydxdiag.pastebin.com/mfagLWnZ
如果有人能解释我为什么会这么慢,我会很高兴。示例代码非常感谢。