При поиске альтернатив для замены GDI я пытался протестировать производительность Delphi 2010 TDirect2DCanvas в Windows 7.
Я протестировал ее, нарисовав огромную ломаную линию с использованием Direct2D, и в результате получилосьабсурдно медленный, даже с объемом данных в 500 раз меньшим, чем тот, который я выполнил в том же тесте с использованием GDI (и я даже не использовал растровое изображение в качестве backbuffer в GDI, я просто обратился непосредственно к холсту формы).
Итак, я думаю, либо:
a) Direct2D медленнее, чем GDI;
b) TDirect2DCanvas медленный;
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 точек полилиний (по крайней мере, 10 000 из них).
Обновлено (2010-11-06)
Ранее я обнаружил, что Direct2D, похоже, не любит полилинии, он рисуется быстрее, если вы используетемного одиночных линий (2 точки полилинии).
Благодаря Крису Бенсену Я обнаружил, что медлительность была с большими полилиниями при использовании сглаживания .Поэтому я отключил сглаживание, как предложил Крис, и производительность рисовалась с ~ 6000 мс до ~ 3500 мс для рисования линий по 50 000.
Все еще можно улучшить, поскольку Direct2D просто не справляется с полилиниями при использованиисглаживание .С отключенным сглаживанием все наоборот.
Теперь время рисования с Direct2D линий 50k, если я рисую большую полилинию без сглаживания, составляет ~ 50 мс.Прекрасно, ах!
Дело в том, что GDI все еще быстрее, чем Direct2D , если я рисую в растровое изображение и после того, как это сделано, я BitBlt результат обратно в форму, он рисует ~ 35 мс и с тем же качеством графики.Кроме того, Direct2D, похоже, уже использует backbuffer (он просто рисует, когда вызывается 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;
Кстати, даже если я использую Крис 'предложение о создании геометрии заранее, скорость примерно равна той же скоростикак GDI, но все же не быстрее.
Мой компьютер нормально работает с приложениями Direct3D и OpenGL, и вот вывод dxDiag: http://mydxdiag.pastebin.com/mfagLWnZ
Я буду рад, если кто-нибудь сможет объяснить мне, почему этомедленность.Пример кода очень ценится.