Было мне нечего делать и решил написать графическую либу, т.к. DirectX'ы и OpenGL'ы учить до ужасного влом. Полноэкранный режим получился сразу нормальным, после долго кипел над оконным. В итоге, получилась поддержка того и другого. Рисовать научил только прямоугольники любых размеров. Решил проверить шустрость и написал тестер, который рисует в окошке 1000 квадратов 32*32 пикселя. FPS всего 30, что мне кажется оооочень медленным, т.к. процедура рисования написана почти полностью на АСМе. Решил сделать процедуру более шустрой. Все умножения заменил сложениями, убрал лишние строчки, но FPS поднялось всего на 1. У меня больше нет идей насчет того, как можно еще больше ускорить процедуру. Есть у кого идеи? Вот код:
- Код: Выделить всё
FUNCTION gRect ALIAS "gRect" (BYVAL hDev AS LONG, _
BYVAL x1 AS LONG, _
BYVAL y1 AS LONG, _
BYVAL x2 AS LONG, _
BYVAL y2 AS LONG, _
BYVAL borderWidth AS LONG, _
BYVAL borderColor AS DWORD, _
BYVAL IsFilled AS LONG, _
BYVAL FillColor AS DWORD _
) EXPORT AS LONG
LOCAL x AS LONG
LOCAL y AS LONG
LOCAL gDev AS LONG PTR
'LOCAL clr AS DWORD
LOCAL offs AS DWORD PTR
LOCAL ddsd AS DDSURFACEDESC PTR
gDev=mmSectionPointer(hDev)
IF y1<=0 THEN y1=1
'if x<0 then x=0
gRect_ok1:
'=================================
offs=@gDev[%lpWidth] '=
'=
'Нулим EAX и ECX '=
! xor ECX,ECX '=
! xor EAX,EAX '=
'=
gRect_loop3: '=
! add EAX,offs '=
! inc ECX '=
! cmp ECX,y1 '=
! jne gRect_loop3 '==\
! add EAX,x1 '===> этот участок является заменой для кода: offs=(@gDev[%lpWidth]*y1+x1)*4+@gDev[%lpSCREENBUFFER]
! mov EBX,EAX '==/
! add EAX,EBX '=
! add EAX,EBX '=
! add EAX,EBX '=
! mov offs,EAX '=
offs=offs+@gDev[%lpSCREENBUFFER]'=
'=================================
LOCAL newline AS DWORD
newline=(@gDev[%lpWidth]-(x2-x1+1))
! mov EAX,newline '\
! add EAX,newline ' \
! add EAX,newline ' умножение newline на 4
! add EAX,newline ' /
! mov newline,EAX '/
! mov ECX,y1 '----------------------------------------[Цикл 1: For y=y1 To y2]--------------------------------------------
gRect_loop1: '|
! mov y,ECX 'Сохраним значение счетчика '|
! mov ECX,x1 '----------------------------[Цикл 2: For x=x1 To x2]------------------------------------ |
gRect_loop2: '| |
! mov x,ECX 'Сохраним значение счетчика | |
'точка за пределами рисуемой области? | |
IF x>=0 AND y>=0 AND x<@gDev[%lpWidth] AND y<@gDev[%lpHeight] THEN '| |
'Нет - рисуем '| |
'Рисуем границу прямоугольника? '| |
IF x<x1+borderWidth OR x>x2-borderWidth OR y<y1+borderWidth OR y>y2-borderWidth THEN '| |
! mov EAX,offs '| |
! mov EBX,borderColor '| |
! mov [EAX],EBX '| |
ELSE 'Нет, это не граница '| |
! cmp isFilled,0 'Применять заливку? '| |
! je RectNotFilled 'Нет? Идем отседава '| |
! mov EAX,offs '| |
! mov EBX,FillColor '| |
! mov [EAX],EBX '| |
RectNotFilled: '| |
END IF '| |
END IF '| |
! add offs,4 'сместим указатель на 4 байта(DWORD) '| |
! mov ECX,x 'Вытащим значение счетчика '| |
! inc ECX 'Увеличим на 1 '| |
! cmp ECX,x2 'Проверим, не достигли ли конца по X '| |
! jna gRect_loop2 'Достигли - уходим------------------------------------------------------| |
'|
! mov EAX,newline 'Рисование строки закончено '|
! add offs,EAX 'Переходим на следующую '|
! mov ECX,y 'Вытащим значение счетчика '|
! inc ECX 'Увеличим на 1 '|
! cmp ECX,y2 'Если это была последняя строка, '|
! jna gRect_loop1 'Уйдем отседа-------------------------------------------------------------------------------|
END FUNCTION