Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как ускорить снятие скриншота, Ассемблерная вставка


Страницы:   1 2 3 4 5 6

Вова ©   (2013-08-14 16:21:00) 

Обнаружил я такой вот код.
Питаю надежду, что он будет работать быстрей моего.

http://www.programmersforum.ru/showthread.php?t=35588

asm
   push esi
   push edx

   mov ecx, BufLength           // размер массива (Integer)
   mov esi, PointerBuf1Scr     // указатель на источник (Pointer)
   mov edx, PointerBuf2Scr    // указатель на приемник (Pointer)

 @@mix:
   movq      xmm0, [esi]     // buf1 -> в регистр
   movq      [edx], xmm0     // buf2 <- из регистра

   add esi, 8
   add edx, 8

   loop @@mix

   pop edx
   pop esi

   emms
 end;


Естественно ничего из написаного мне не понятно. Но исходя из контекста у меня возникло ощущение, что это можно использовать для снятия скриншота. Только вот как это должно выглядеть на делфи я не знаю. В общем то в этом и вопрос.


Procedure   TMyObject.getScreen(var tbmp: Tbitmap; tmpCoord: TCoord);
var
 hDC1: HDC;
 R: TRect;
 Canvas: TCanvas;
begin

 if tmpCoord.x2search = 0 then
   tmpCoord.x2search := screen.Width;

 if tmpCoord.y2search = 0 then
   tmpCoord.y2search := screen.Height;

 hDC1 := GetDC(0);
 Canvas := TCanvas.Create();
 Canvas.Lock;
 Canvas.Handle := hDC1;
 R := Rect(tmpCoord.x1search, tmpCoord.y1search, tmpCoord.x2search,
   tmpCoord.y2search);

 tbmp              := Tbitmap.Create;
 tbmp.Canvas.Lock;
 tbmp.Width        := R.Right  - R.Left;
 tbmp.Height       := R.Bottom - R.Top;
 tbmp.PixelFormat  := pf24bit;
 tbmp.Canvas.CopyRect(Rect(0,0,tbmp.Width,tbmp.Height), Canvas, R);

 ReleaseDC(0, hDC1);
 Canvas.Free;
 Canvas.Unlock;

end;


как то так делался у меня скриншот, ну примерно в общем не суть, как это объединить?


Sapersky   (2013-08-15 18:10:00) [81]

В данном случае ради результата как раз не стоит заморачиваться - наверняка копирование картинки (тем более фрагмента картинки) не будет узким местом, всё остальное будет тормозить сильнее. BitBlt с экрана, обработка, сжатие или что там у тебя - на этом фоне ускорение копирования в 2 раза не будет заметно.


> Как его выровнять? потому что я так и не понял, почему это
> адрес вдруг кратен 16 )

Требование такое у SSE-команд, иначе вываливается с ошибкой.
Если битмап 32-битный, значит x-координата должна быть кратна 4.


Вова   (2013-08-15 17:36:00) [82]

Я ведь делфи когда учил я не потому это делал, что мне нужно было стать мастером делфи, а потому что мне нужно было что то сделать и я так же мыкался, прогресс по моему на лицо )


Вова   (2013-08-15 17:34:00) [83]



> IMHO, значит, рано ещё про ассемблер думать.


IMHO мне нужен конкретный результат, а не ассемблер или что либо еще, так что  это неправильное ИМХО


ProgRAMmer Dimonych   (2013-08-15 17:26:00) [84]

> [17] Вова   (15.08.13 16:01)
> потому что я так и не понял, почему это адрес вдруг кратен
> 16 )

IMHO, значит, рано ещё про ассемблер думать.


Вова   (2013-08-15 16:01:00) [85]

нет...буду копировать квадрат по случайным координатам, ну можно увеличить немного квадрат. 32 битный битмап сделаю. Как его выровнять? потому что я так и не понял, почему это адрес вдруг кратен 16 )


Sapersky   (2013-08-15 15:20:00) [86]


> >  и выравнивание на 16
эт что значит?

Адреса Src, Dst должны быть кратны 16. Для битмапов это условие выполняется, если будешь копировать полностью (ну или фрагмент с начала).

MMX-у в [0] тоже требуется выравнивание на 8, иначе никакого ускорения в принципе не получится.


брат Птибурдукова   (2013-08-15 12:23:00) [87]


> hSrcDC := CreateDC('DISPLAY', Nil, nil, nil);  hDC1 := CreateCompatibleDC(hSrcDC);
а это зачем?


Вова   (2013-08-15 09:49:00) [88]

Procedure getScreen(var tbmp: TBitmap; tmpCoord: TCoord);
var
 hDC1: HDC;
 hSrcDC: HDC;
 hBmp: HBITMAP;
 R: TRect;
begin

 if tmpCoord.x2work = 0 then
   tmpCoord.x2work := screen.Width;

 if tmpCoord.y2work = 0 then
   tmpCoord.y2work := screen.Height;

 tbmp.Canvas.Lock;

 R := Rect(tmpCoord.x1work, tmpCoord.y1work, tmpCoord.x2work, tmpCoord.y2work);

 tbmp.Width  := R.Right  - R.Left;
 tbmp.Height := R.Bottom - R.Top;

 hSrcDC := CreateDC('DISPLAY', Nil, nil, nil);
 hDC1 := CreateCompatibleDC(hSrcDC);
 SelectObject(hDC1, tbmp.Handle);
 BitBlt(hDC1, 0, 0, tbmp.Width, tbmp.Height, hSrcDC, tmpCoord.x1work,
   tmpCoord.y1work, SRCCOPY);

 tbmp.PixelFormat := pf24bit;
 DeleteDC(hDC1);
 DeleteDC(hSrcDC);
 tbmp.Canvas.Unlock;
end;


вот такая актуальная моя процедура. без пиксель формата почему то не работает, потом посмотрю.


Вова   (2013-08-15 09:46:00) [89]


> BitBlt(bmp.Canvas.Handle, 0, 0, Screen.Width, Screen.Height,
>   DC, 0, 0, SRCCOPY);


не, это уже есть.

эх....ну вот) а у меня уже пришла идея бил битом делать скрин в отдельном потоке, а потом этой штукой копировать его тыщу раз...а она оказываецо плохая (


>  и выравнивание на 16


эт что значит?


Sapersky   (2013-08-15 02:49:00) [90]

Ну да, BitBlt.
Но это же скучно, то ли дело - такты считать :)

procedure CopySSE(Src, Dst : Pointer; Cnt : Integer);
asm
   shr ecx, 5
 @@mix:
   movapd xmm0, [eax]
   movapd xmm1, [eax+16]
   movapd [edx], xmm0
   movapd [edx+16], xmm1
   add eax, 32
   add edx, 32
   dec ecx
   jnz @@mix
end;

В 2 раза быстрее Move, но работает только для идеальных случаев - кратный 32 размер и выравнивание на 16.
Неидеальные мне лень обрабатывать, возможно это сделано в FastCode Move Challenge, там были варианты с SSE.


Smile   (2013-08-15 00:03:00) [91]

Куда спешим с ASM?

DC: HDC;

BitBlt(bmp.Canvas.Handle, 0, 0, Screen.Width, Screen.Height,  DC, 0, 0, SRCCOPY);

не???


Rouse_   (2013-08-14 23:43:00) [92]

Врочем - код не рабочий чуть более чем полностью :)
В ХЕ4 плывет, а в семерке CopyMemory в 6 раз быстрее чем "это"...


Rouse_   (2013-08-14 23:28:00) [93]


> Наверное, по размеру оптимизируют :) Хотя без процедуры
> компактнее было бы.

Допустим, но тут другое, это делается в разы проще и гораздо быстрее.
Если человек начинает писать на ассемблере, он должен понимать - зачем он это делает, чтоб не получить такой-вот грустный код...


ProgRAMmer Dimonych   (2013-08-14 23:19:00) [94]

> [7] Rouse_ ©   (14.08.13 22:58)

Наверное, по размеру оптимизируют :) Хотя без процедуры компактнее было бы.


Rouse_   (2013-08-14 22:58:00) [95]

да еще и "loop", мндя...


Rouse_   (2013-08-14 22:56:00) [96]


>   movq      xmm0, [esi]     // buf1 -> в регистр
>   movq      [edx], xmm0     // buf2 <- из регистра

12 тактов на перемещение 8 байт? Оптимизация "однако"...


Sapersky   (2013-08-14 17:40:00) [97]

BitBlt дёргает функции драйвера видеокарты.
Больше ты до них никак не доберёшься, разве что через другой API (DirectX), но по моему опыту в этом нет смысла - копирование картинки работает (если усреднить результаты на разном железе) с одинаковой скоростью на любых API.


Вова   (2013-08-14 17:23:00) [98]

но BitBlt как то же получает его из видеопамяти?

моя практика показывает, что WinApi функции далеки от идеалов быстроты.


Sapersky   (2013-08-14 17:03:00) [99]

А источник в видеопамяти. То есть - нет, не поможет.

Может немного помочь использование 32-битного битмапа вместо 24 и (возможно) BitBlt вместо CopyRect, т.к. CopyRect вызывает StretchBlt.

Если скриншот подразумевается не один, то создавать/задавать размеры битмапа заранее. При этом лучше сначала задать PixelFormat, потом Width/Height.


Вова   (2013-08-14 16:37:00) [100]


h                        := R.Bottom - R.Top - 1;
w                       := R.Right  - R.Left;
BufLength           := (h+1)*w;
PointerBuf2Scr    := tbmp.ScanLine[h];


так??
а источник???


Страницы:   1 2 3 4 5 6

Наверх

Титульная страница Поиск, карта сайта Написать письмо