Page 4 of 7

Re: Векторные функции

Posted: Sun Oct 04, 2009 6:44 pm
by andrew_programmer
ты имееш ввиду libGUI ? В каком файле код ?
Да. Код в файле draw_controls.inc Только код полностью на C. Если написать на ассемблере, то быстрее будет работать. Реализовать функцию рисующую и на экране и в буфере можно по разному. У меня реализовано так:

Code: Select all

void DrawPixel(int x,int y,DWORD color)
{
	char		r,g,b;
	char		*ptr;
	DWORD	*ptr2;

	if (x>screen.size_x-1) {x=screen.size_x-1;}
	if (y>screen.size_y-1) {y=screen.size_y-1;}
	if (x<0) {x=0;}
	if (y<0) {y=0;}

	switch(screen.draw_output)
	{
		case DRAW_OUTPUT_SCREEN:
		{
			x+=screen.x;
			y+=screen.y;
			gui_ksys_put_pixel_window(x,y,color);
			break;
		}
		case DRAW_OUTPUT_BUFFER:
		{
			ptr=screen.buffer;
			switch(screen.bits_per_pixel)
			{
				case 24:
				{
					ptr=ptr+(y*screen.size_x+x)*3;
					b=color & 0xff;
					color=color >>8;
					g=color & 0xff;
					color=color >>8;
					r=color & 0xff;

					ptr[0]=b;
					ptr[1]=g;
					ptr[2]=r;
					break;
				}
				case 32:
				{
					ptr2=(DWORD*)ptr+y*screen.size_x+x;
					*ptr2=color;
					break;
				}
				default: break;
			}
			break;
		}
	}
}


Функций, непосредственно работающих с экраном/буффером 4: DrawPixel(),DrawHorizontalLine(),DrawVerticalLine(),DrawImage(). Все остальные функции рисования используют эти 4. В результате можно рисовать как на экране, так и в буффере.

Re: Векторные функции

Posted: Mon Oct 05, 2009 6:46 am
by Albom
andrew_programmer
Я бы в начале функции проверку на выход за границы изменил бы на такую:

Code: Select all

if  ( (x>screen.size_x-1) || (y>screen.size_y-1) || (x<0) || (y<0) )
         return;

Re: Векторные функции

Posted: Mon Oct 05, 2009 2:51 pm
by andrew_programmer
Да, для отдельных пикселей лучше так.
Эта проверка границ у меня взята из вывода геометрических примитивов. Там просто так отсекать вывод по границам нельзя. Видимо забыл поменять код. Когда дело дойдёт до полной оптимизации функций рисования, то я всеми этими вещами займусь.

Re: Векторные функции

Posted: Mon Oct 05, 2009 11:06 pm
by IgorA
что-бы не мигало и быстрее выводило при прорисовке добавил возможность вывода через буфер. Появилось 5 функций для работы с буфером (создание, удаление, очистка, вывод на экран, установка активного буфера). Пока поддерживается только 1 буфер, но в будущем можно будет расширить их число.
Старый вариант работы, с выводом на экран тоже возможен. В архиве 2 программы используют буфер, остальные рисуют напрямую в экран.
Шрифт вроде стал работать быстрее.

Re: Векторные функции

Posted: Mon Oct 05, 2009 11:39 pm
by IgorA
переделал еще 1 пример под буфер, точно быстрее выводит :D

Re: Векторные функции

Posted: Tue Oct 06, 2009 12:02 am
by Gluk
вообще супер! =)

Re: Векторные функции

Posted: Tue Oct 06, 2009 1:07 am
by andrew_programmer
В коде попиксельного рисования в буфере желательно заменить вот это:

Code: Select all

drawpixel_buf:
  bt bx,15
  jc @f
  bt cx,15
  jc @f
  cmp bx,word[active_buffer_w]
  jge @f
  cmp cx,word[active_buffer_h]
  jge @f
  push edi esi
  mov edi,dword[active_buffer] ;ptr - pointer to buffer
  mov esi,ebx ;esi=coord x
  imul esi,3 	;x*3
  add edi,esi	;ptr+x*3

  xor esi,esi
  mov si,word[active_buffer_w] ;size x
  imul esi,ecx ;size_x*y	
  imul esi,3	;size_x*y*3
  add edi,esi	;ptr+x*3+size_x*y*3
  mov word[edi],dx ;
  ror edx,16		
  mov byte[edi+2],dl
  ror edx,16
  pop esi edi
  @@:
  ret
хотя бы на это

Code: Select all

 drawpixel_buf:
  bt bx,15
  jc @f
  bt cx,15
  jc @f
  cmp bx,word[active_buffer_w]
  jge @f
  cmp cx,word[active_buffer_h]
  jge @f
  push esi
  xor esi,esi
  mov si,word[active_buffer_w] ;size x
  imul esi,ecx	;size_x*y
  add esi,ebx	;size_x*y+x
  lea esi,[esi+esi*2] ;(size_x*y+x)*3
  add esi,dword[active_buffer] ;ptr+(size_x*y+x)*3
  
  mov word[esi],dx ;
  ror edx,16		
  mov byte[esi+2],dl
  ror edx,16
  pop esi
  @@:
  ret
Небольшие рекомендации.
В коде попиксельного рисования отдельного вида кривой желательно сделать как можно меньше обращений к системной памяти. То есть желательно отказаться от push/pop для функции попиксельного рисования. Перед вызовом drawpixel_buf необходимые параметры поместить в регистры(указатель на буфер, его ширина и высота). Если последовательно рисуется множество точек одной кривой, то заранее размещённые в регистрах параметры дадут очень существенное ускорение работы. Скорость работы регистровой памяти значительно выше, чем системной.

Re: Векторные функции

Posted: Tue Oct 06, 2009 10:08 am
by Mario
Добавлю пять копеек:
1) Если условно разбить буфер на знакоместа определенного размера (например, 50х50 пикселов) и дополнительно использовав область для хранения признака обновления знакоместа, можно немного ускорить вывод обновляя только те знакоместа, в которые производился вывод. Конечно при вызове перерисовки окна нужно перерисовывать весь буфер, но потом достаточно только перерисовывать изменения. Особенно заметна будет разница в скорости на полноэкранных приложениях, при обновлении небольших участков.
2) Имеет смысл сделать буфер чуть большим отображаемого куска на экране, иначе у жучары части пропадают в некоторых ракурсах.

Re: Векторные функции

Posted: Tue Oct 06, 2009 1:21 pm
by IgorA
andrew_programmer согласен что не оптимально, перекомпилировал, работает. Только не пойму как вместо умножения на 3 написано:

Code: Select all

  lea esi,[esi+esi*2] ;(size_x*y+x)*3
почему не так:

Code: Select all

  imul esi,3
или так:

Code: Select all

  lea esi,[esi*3] ;(size_x*y+x)*3

Re: Векторные функции

Posted: Tue Oct 06, 2009 1:57 pm
by Mario
IgorA wrote: почему не так:

Code: Select all

  imul esi,3
или так:

Code: Select all

  lea esi,[esi*3] ;(size_x*y+x)*3
1. Потому что IMUL теоретически медленней.
2. Потому что Зубков.

Code: Select all

Команда LEA
LEA можно использовать (кроме прямого назначения — вычисления адреса сложно адресуемой переменной) для следующих двух ситуаций:

быстрое умножение 
        lea        еах,[еах*2]     ; ЕАХ = ЕАХ * 2 (shl eax,1 лучше)

        lea        еах,[еах+еах*2]  ; ЕАХ = ЕАХ * 3
        lea        еах,[еах*4]      ; ЕАХ = ЕАХ * 4 (shl eax,2 лучше)

        lea        еах,[еах+еах*4]  ; ЕАХ = ЕАХ * 5
        lea        еах,[еах+еах*8]  ; ЕАХ = ЕАХ * 9

трехоперандное сложение 
        lea        ecx,[eax+ebx]    ; ЕСХ = ЕАХ * ЕВХ

Единственный недостаток LEA — увеличивается вероятность AGI с предыдущей командой (см. ниже).

Re: Векторные функции

Posted: Tue Oct 06, 2009 2:18 pm
by andrew_programmer
почему не так:
imul esi,3
Потому что так на умножение уйдёт минимум 10 тактов. А при помощи командыlea esi,[esi+2*esi] всего 2-3 такта.
почему не так:
imul esi,3
или так:
lea esi,[esi*3] ;(size_x*y+x)*3
С учётом того, что команда lea может выполняться одновременно с другой командой в любом конвеере, получается, что по скорости кода lea esi,[esi*3] =imul esi,3

Для процессора умножение на 2 в степени n - это просто сдвиг на n бит влево. Операция сложения, также как и команда lea тоже может выполняться в любом конвеере. В общем вычисление адреса вместе с занесением его в ESI занимает минимум 2-3 такта, против минимум 10 в случае с imul.

Re: Векторные функции

Posted: Wed Oct 07, 2009 2:41 pm
by IgorA
Сделал 3 изменения:
1) исправил функцию рисования точки в буфере, как сказал andrew_programmer
2) доработал алгоритм отсечения кривых, когда они попадают на верхнюю и на левую границу окна
3) можно использовать несколько отдельных буферов (номера принимают функции на входе, максимум 8 буферов, хотя при необходимости можно добавить)

Дописал справку, под новые функции.

Re: Векторные функции

Posted: Wed Oct 07, 2009 3:49 pm
by Albom
в документации опечаточка. нужно исправить "длинна" на "длина"

Re: Векторные функции

Posted: Wed Oct 07, 2009 7:35 pm
by Ghost
IgorA
Делай больше коментариев в коде, и перед каждой функцией желатьельно, полез посмотреть - все равно что в IDA посмотрел, найдется мало желающих помогать в разработке.

Re: Векторные функции

Posted: Wed Oct 07, 2009 7:52 pm
by IgorA
Albom
Исправлю
Ghost
Я более подробно пробовал писать в документации. Но могу и в коде больше коментов написать. Если писать комментарии в коде, то в какой кодировке лучше OEM или ANSI?
Ghost wrote:больше коментариев в коде, и перед каждой функцией желатьельно
Имеешь в виду саму библиотеку или ее использование. Или и то и другое?