flat assembler
Message board for the users of flat assembler.
Index
> OS Construction > drawing a line on the screen? |
Author |
|
Dex4u 14 Mar 2005, 17:04
In the Cdpod code is code that draws line's etc, the X Y of the line in the cdpod code is hard coded, so you will need to change this to use var for X Y.
You can get "CdPod.zip" here: http://board.flatassembler.net/topic.php?t=2164&start=50 |
|||
14 Mar 2005, 17:04 |
|
bogdanontanu 15 Mar 2005, 00:12
I was going to post some Bresenham code for a general line draw; it will be in Solar OS next version anyway.
But for buttons you mainly need horizontal, vertical and eventually diagonal lines. That is already available and pretty easy to do yourself |
|||
15 Mar 2005, 00:12 |
|
Pharabee 01 Apr 2005, 07:59
I only have this for MASM32. It slow, real slow. But this is simple.
Code: invoke GetDeltaXY,x,y,x2,y2 mov nDX,edx mov nDY,eax invoke GetHypotenusa,nDX,nDY mov hyp,eax cmp hyp,0 jle brs mov ecx,hyp @@: push ecx invoke GetPosLine,nDX,nDY,hyp,ecx add edx,x add eax,y invoke YourPixelFunction,edx,eax,color pop ecx dec ecx jnz @b brs: ret GetPosLine proc nDX:dword,nDY:dword,hyp:dword,nPos:dword LOCAL x,y:dword fild nDX fidiv hyp fimul nPos fistp x ; (nPos*nDX)/hyp ; xor edx,edx ; 1 ; xor eax,eax ; 1 ; mov eax,nDX ; 1 ; mul nPos ; 42 ; div hyp ; 42 ; mov x,eax ; 1 fild nDY fidiv hyp fimul nPos fistp y ; (nPos*nDY)/hyp ; xor edx,edx ; 1 ; xor eax,eax ; 1 ; mov eax,nDY ; 1 ; mul nPos ; 42 ; div hyp ; 42 ; mov y,eax ; 1 mov edx,x mov eax,y ; FPU = 169 Clock cycle ; No FPU = 177 Clock cycle ret GetPosLine endp ; Result on edx:eax GetDeltaXY proc x:dword,y:dword,x2:dword,y2:dword mov edx,x2 sub edx,x mov eax,y2 sub eax,y ret GetDeltaXY endp ; Result on edx:eax GetHypotenusa proc nDX:dword,nDY:dword LOCAL res:dword xor edx,edx mov eax,nDY mul eax mov res,eax mov eax,nDX mul eax add res,eax fild res fsqrt fistp res mov eax,res ret GetHypotenusa endp ; _________________ How to Get work Fast: 10% Skill, 90% honesty. |
|||
01 Apr 2005, 07:59 |
|
joachim_neu 01 Apr 2005, 08:11
well, i'm doing this at the moment, too. the problem i got was not the mathematic but if the X-difference was smaller than the Y-difference my code built me this:
Code: X X X X instead of this: Code: X X X X X X ... but i think i'll do it with offsets and operating directly in the video-ram. that should be faster, but complexer, too, i think. J!N |
|||
01 Apr 2005, 08:11 |
|
MCD 01 Apr 2005, 09:25
joachim_neu wrote: well, i'm doing this at the moment, too. the problem i got was not the mathematic but if the X-difference was smaller than the Y-difference my code built me this: It's usually much slower than writing it first to an offscreen buffer. Copy the result to the video RAM as a last step. And to your problem with the falsely drewn lines: The algorythm you use is easy to understand, but it needs some unpretty correcting from the raw mathematical formulas: IF X1-X2 > Y1-Y2 THEN do exactly the kind of algorythm you are using now ELSE do the line algorythm, but advance on the Y coordinates instead of advancing on the X coordinates on each next pixel. END IF 1 tip: You should furthermore check if your line algorythm doesn't produce "(floatin point) divide by 0" exceptions when drawing exact horizontal or vertical lines, because all line algorythm I know use some kind of dividing to calculate some DeltaY/DeltaY ratio. Anyway, as bogdanontanu noticed, the Bresenham algorythm is better. _________________ MCD - the inevitable return of the Mad Computer Doggy -||__/ .|+-~ .|| || |
|||
01 Apr 2005, 09:25 |
|
f0dder 01 Apr 2005, 11:50
first - don't call a putpixel routine, that will be *very* slow - do the pixel plotting directly. Next, google for "bresenham" if you need an algorithm that draws proper lines.
|
|||
01 Apr 2005, 11:50 |
|
tom tobias 01 Apr 2005, 12:27
f0dder wrote: first - don't call a putpixel routine, that will be *very* slow - do the pixel plotting directly. Next, google for "bresenham" if you need an algorithm that draws proper lines. Neither the Bresenham algorithm, nor any other "fast" method of drawing a line, will overcome the principle difficulty: accessing the hardware, i.e. video controller, directly. Unfortunately, EACH video controller is different. Most are proprietary and will not release the information needed to access the "secret" registers to illuminate specific pixels at particular times. Older video controllers are better documented, if you have a Trident controller you may be able to get the information you need. Ferraro's book (1993) describing the programming of video controllers will be useful for accessing a Trident controller, and Michael Abrash's book could also offer some ideas for other controllers. Both books have been out of print for several years. |
|||
01 Apr 2005, 12:27 |
|
PopeInnocent 01 Apr 2005, 21:16
"The Zen of Graphics Programming" by Michael Abrash dedicates 4 chapters (IIRC) to the Bresenham line drawing algorithm. One of the interesting things he does in the later chapters is that he separates the calculation of the line (the Bresenham algorithm) from the actual (device-dependent) rendering.
I'll see if I can dig up some 16-bit code I wrote way back when based on Abrash's methods. Quote: Unfortunately, EACH video controller is different. That's why VESA VBE was invented. |
|||
01 Apr 2005, 21:16 |
|
MCD 04 Apr 2005, 07:32
Okay, it took me a day, but here I finally got a bresenham line drawing approach. Unfortunately, I have little time, so it's not finished. It especially lacks a (complementary) part that draws lines whith |Y2-Y1| > |X2-X1|, let's call them vertical lines. You will also have to check for this in a arbitrary line drawing procedure. Furthermore it lacks any out-of-screen-border checks.
Code: ;edx: X1 ;ebx: Y1 ;ecx: X2 ;eax: Y2 ;esi: # of bytes from pixel(X,Y) to pixel(X,Y+1) ;edi: base offset of buffer to draw to ;ebp: color Line: push eax ecx edx ebx esi edi sub ecx,edx ;Calc deltaX:= (X2-X1) & check if (X1;Y1) and (X2;Y2) coords must be swapped - in the same instruc jae .DontXchCoords neg ecx ;Swapping deltaX results in changing its sign xchg eax,ebx ;But Y coords are swapped the usual way .DontXchCoords: sub eax,ebx ;deltaY:= Abs(Y2-Y1) imul ebx,esi ;Calc ofs of first pixel:= Y1*#OfBytesBetween2ConsecutiveVertPixels + X1*4 add edx,ecx lea edi,[edi+edx*4+4] add edi,ebx cdq xor eax,edx sub eax,edx xor esi,edx ;Negate #OfBytesBetween2ConsecutiveVertPixels... sub esi,edx ;...if line goes upwards, this is when Y2 < Y1 mov edx,ecx ;Init total pixel counter with -deltaX not edx mov ebx,ecx ;deltaX in ebx shr ecx,1 ;Init step counter with deltaX/2 .PutPixel: mov [edi+edx*4],ebp ;I guess you guess it inc edx ;Inc total pixel counter until line ends jz .Done sub ecx,eax ;Decrease step counter by step size jnc .PutPixel ;Start new step if end of current step reached add edi,esi ;Go 1 pixel down or up add ecx,ebx ;Add deltaX to step counter jmp .PutPixel .Done: pop edi esi ebx edx ecx eax ret It seems quiet speed optimized for me, but there may still be several improvements. (jump hints, but PIV only ). The only thing I know is that the complete memory addressing [edi+edx*4] doesn't slow it down, but is even a bit faster than [edi] and doing the rest with more instructions (Tested, about 14%). I guess MMX/SSE won't bring much here. _________________ MCD - the inevitable return of the Mad Computer Doggy -||__/ .|+-~ .|| || |
|||
04 Apr 2005, 07:32 |
|
Pharabee 09 Apr 2005, 07:21
MCD wrote: Okay, it took me a day, but here I finally got a bresenham line drawing approach. Unfortunately, I have little time, so it's not finished. It especially lacks a (complementary) part that draws lines whith |Y2-Y1| > |X2-X1|, let's call them vertical lines. You will also have to check for this in a arbitrary line drawing procedure. Furthermore it lacks any out-of-screen-border checks. Hi good job. I like this. I take this on my code. _________________ How to Get work Fast: 10% Skill, 90% honesty. |
|||
09 Apr 2005, 07:21 |
|
MCD 11 Apr 2005, 09:41
Thanks, it's rather KISS. I've not finished the vertical part yet, because I'm very busy at the moment and a difficult problem arose: In order to also the vertical main loop fast, I would need one more general register, because the "INC EDX" instruction must be changed to something like "ADD EDX,SomeOtherRegisterX", but unfortunately we don't have any register left. Furthermore all registers used in the main loop are really needed, e.g. cannot be written with less registers. So I have currently different options:
-Use the stack to push and pop 1 register in the part of the main loop where the next step is being taken. -Do the above, but with a temp variable in either code or data segment, not in the stack. -For god's sake save to a temporal variable and sacrify this goddamnned ESP register, but I guess Windows doesn't like this approach Well I should also test then which one is the fastest. _________________ MCD - the inevitable return of the Mad Computer Doggy -||__/ .|+-~ .|| || |
|||
11 Apr 2005, 09:41 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.