![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Быстрое копирование битмапов [D5, D6, D7, Win2k, WinXP]
antonn © (2008-01-12 18:04:00)Пересечение веток:
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1192964708&n=7
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1192295230&n=7
и теста http://www.delphimaster.ru/cgi-bin/forum.pl?id=1200137908&n=3
Собсно, есть код блитинга битмапов (TBitmap, 32bit), который почему то медленно выполняется на АМД (медленно относительно оппонентов от Интел, я понимаю, что может там мега процы начали делать, но не настолько же круто). Помогите дооптимизировать его :)
OSokin (2008-01-15 20:04:00) [1]о_О а разве loop @a не равен dec cx / jnz @a ???
А xor вместо cmp дает что-нибудь?
antonn (2008-01-15 18:34:00) [2]кстати) если вставить loop и убрать dec - ошибок нет, все выполняется) вот только блитится ровно половина (слева) битмапа, поэтому очень быстро:)
OSokin (2008-01-15 18:32:00) [3]Тьфу, блин. Перепутал результаты =)
antonn (2008-01-15 18:28:00) [4]
> OSokin (15.01.08 18:12) [7]
верни обратноdec ecxи получишь еще медленней :)
OSokin (2008-01-15 18:12:00) [5]А если вот так?
push ebx
push edi
push esi
mov ebx, TransColor
and ebx, $FFFFFF
@outer_loop:
mov edi, DstBits
mov ecx, sx
mov esi, SrcBits
@loop:
mov eax, [esi]
mov edx, eax
and eax, $FFFFFF
add esi, 4
xor eax, ebx
jz @next
mov [edi], edx
@next:
add edi, 4
loop @loop
@end:
mov ecx, inc1
mov eax, inc2
add DstBits, ecx
add SrcBits, eax
dec sy
jnz @outer_loop
pop esi
pop edi
pop ebx
Замена на луп дает выйгрыш в 1 байт =). Правда, не проверял, будет работать или нет, но твоя тестилка, модифицированная hiew'ом =), выдает такой результат:
Draw alpha with a: 7,32291837279389
Draw alpha: 5,28911366240431
Draw alpha MMX: 1,9601630027934
Draw transparent color: 0,899604913674843
Draw tr. color opacity MMX: 2,22137304124701
Draw rotate alpha: 9,56283062961568
До этого было так:
Draw alpha with a: 7,925456581538
Draw alpha: 5,84321204678404
Draw alpha MMX: 2,16867349828345
Draw transparent color: 0,993406174967481
Draw tr. color opacity MMX: 2,45866821997455
Draw rotate alpha: 10,6337005945738
Kenny (2008-01-13 22:36:00) [6]Draw alpha with a: 2,8802308673309
Draw alpha: 1,64891236176665
Draw alpha MMX: 1,54101373219222
Draw transparent color: 1,17464649836781
Draw tr. color opacity MMX: 1,5966358852871
Draw rotate alpha: 5,10885266144161
---
Pentium M (1.73 Ghz, 533Mhz FSB, 2MB L2 cache)
antonn [work) (2008-01-13 21:53:00) [7]мне на асме проще )
Sapersky (2008-01-13 19:55:00) [8]Можно попробовать CMOV. Но по моему опыту (на другом алгоритме), толку от неё чуть.
А если без спец. инструкций - то и asm необязателен, компилятор вполне справляется. Ну будет разница процентов 5, и то не факт, что в пользу "рукописного" варианта.
Dib@zol (2008-01-13 18:45:00) [9]and ebx, $FFFFFF
А нужно ли затирание верхнего байта там, где он не используется? Нафик ету строчку :)
mov eax, [esi]
mov edx, [esi]
Чтобы не "дёргать" память дважды, можно заменить последнюю строчку на mov edx, eax. Правда, прирост производительности при этом мизерный, но етож всётки цикл :)
А вообще занятный алгоритм. Щас вот думаю, как повязать SrcBits и DstBits на EBP и ESP.
antonn (2008-01-12 18:07:00) [10]ЗЫ понятно дело, что для операций в цикле вычисление адреса первой строки пикселов можно куда нибудь вынести. Но в циклах гонялись битмапы 1600*1200, основная нагрузка идет в асме.
antonn (2008-01-12 18:05:00) [11]код:
procedure DrawBitmap_transcolor(BTSource,BTDest:TBitmap; _x,_y:integer; transcolor:TColor);
var SrcBits: pointer; DstBits: pointer;
xTo, sx, YTo, ddx, ddy, sy, w, h, dstw, dsth: integer;
inc1, inc2: integer;
Sfscanline0,Dfscanline0,fbits:pointer;
function DIBBits(BMP: TBitmap): Pointer;
var Section:TDIBSECTION;
begin
BMP.HandleType:=bmDIB;
GetObject(BMP.Handle,sizeof(TDIBSECTION),@Section);
Result:=Section.dsBm.bmBits;
end;
begin
w:=BTSource.Width; h:=BTSource.Height;
dstw:=BTDest.Width; dsth:=BTDest.Height;
XTo:=_x+W-1; YTo:=_y+H-1;
if(_y>=dstH)or(_x>=dstW)or(YTo<0)or(XTo<0) then exit;
asm
xor eax, eax
mov ddx, eax
mov ddy, eax
end;
sx:=W;
sy:=H;
if _x<0 then begin
ddx:=-_x;
inc(sx,_x);
_x:=0;
end;
if _y<0 then begin
ddy:=-_y;
inc(sy,_y);
_y:=0;
end;
if XTo>=dstw then dec(sx,XTo-dstw+1);
if YTo>=dsth then dec(sy,YTo-dsth+1);
if (sx<=0)or(sy<=0) then exit;
inc2:=-(((32*w+31) shr 3) and $FFFFFFFC);
Sfscanline0:=pointer(integer(DIBBits(BTSource))+abs(inc2)*(h-1));
SrcBits:=pointer(integer(Sfscanline0)+inc2*ddy+ddx*4);
inc1:=-(((32*dstw+31) shr 3) and $FFFFFFFC);
Dfscanline0:=pointer(integer(DIBBits(BTDest))+abs(inc1)*(dsth-1));
DstBits:=pointer(integer(Dfscanline0)+inc1*_y+_x*4);
asm
push ebx
push edi
push esi
mov ebx, TransColor
and ebx, $FFFFFF
@outer_loop:
mov edi, DstBits
mov ecx, sx
mov esi, SrcBits
@loop:
mov eax, [esi]
mov edx, [esi]
and eax, $FFFFFF
add esi, 4
cmp eax, ebx
jz @next
mov [edi], edx
@next:
add edi, 4
dec ecx
jnz @loop
@end:
mov ecx, inc1
mov eax, inc2
add DstBits, ecx
add SrcBits, eax
dec sy
jnz @outer_loop
pop esi
pop edi
pop ebx
end;
end;
функция быстрого блитинга, затирает альфаканал.