From 69d839e89162333cb464ad2c299c3a3572de283f Mon Sep 17 00:00:00 2001 From: nickysn Date: Tue, 17 Mar 2015 00:13:58 +0000 Subject: [PATCH] + implemented VESA banked 32k/64k colour mode fast line drawing in the go32v2 graph unit git-svn-id: trunk@30246 - --- packages/graph/src/go32v2/graph.pp | 1 + packages/graph/src/go32v2/vesa.inc | 317 +++++++++++++++++++++++++++++ 2 files changed, 318 insertions(+) diff --git a/packages/graph/src/go32v2/graph.pp b/packages/graph/src/go32v2/graph.pp index e7f66afa73..e71123e47c 100644 --- a/packages/graph/src/go32v2/graph.pp +++ b/packages/graph/src/go32v2/graph.pp @@ -3550,6 +3550,7 @@ const CrtAddress: word = 0; mode.GetRGBPalette := {$ifdef fpc}@{$endif}GetVESARGBPalette; mode.SetVisualPage := {$ifdef fpc}@{$endif}SetVisualVESA; mode.SetActivePage := {$ifdef fpc}@{$endif}SetActiveVESA; + mode.HLine := {$ifdef fpc}@{$endif}HLineVESA32kOr64k; end; procedure FillCommonVESA32k(var mode: TModeInfo); diff --git a/packages/graph/src/go32v2/vesa.inc b/packages/graph/src/go32v2/vesa.inc index b2919f65ed..f2b1fc59fe 100644 --- a/packages/graph/src/go32v2/vesa.inc +++ b/packages/graph/src/go32v2/vesa.inc @@ -1377,6 +1377,323 @@ end; End; end; + procedure HLineVESA32kOr64k(x,x2,y: smallint); {$ifndef fpc}far;{$endif fpc} + + var Offs: Longint; + mask, l, bankrest: longint; + curbank, hlength: smallint; + Begin + { must we swap the values? } + if x > x2 then + Begin + x := x xor x2; + x2 := x xor x2; + x:= x xor x2; + end; + { First convert to global coordinates } + X := X + StartXViewPort; + X2 := X2 + StartXViewPort; + Y := Y + StartYViewPort; + if ClipPixels then + Begin + if LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort, + StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then + exit; + end; + {$ifdef logging2} + LogLn('hline '+strf(x)+' - '+strf(x2)+' on '+strf(y)+' in mode '+strf(currentwritemode)); + {$endif logging2} + HLength := x2 - x + 1; + {$ifdef logging2} + LogLn('length: '+strf(hlength)); + {$endif logging2} + if HLength>0 then + begin + Offs:=(Longint(y)+YOffset)*bytesperline+2*x; + {$ifdef logging2} + LogLn('Offs: '+strf(offs)+' -- '+hexstr(offs,8)); + {$endif logging2} + Mask := longint(word(CurrentColor)+word(CurrentColor) shl 16); + Case CurrentWriteMode of + AndPut: + Begin + Repeat + curbank := smallint(offs shr 16); + SetWriteBank(curbank); + SetReadBank(curbank); + {$ifdef logging2} + LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8)); + {$endif logging2} + If ((HLength >= 2) and + ((offs and 3) = 0)) or + (HLength >= 3) Then + { align target } + Begin + If (offs and 3) <> 0 then + { this cannot go past a window boundary because the } + { size of a window is always a multiple of 4 } + Begin + {$ifdef logging2} + LogLn('Aligning by drawing 1 pixel'); + {$endif logging2} + MemW[WinWriteSeg:word(offs)] := + MemW[WinReadSeg:word(offs)] And Word(CurrentColor); + Dec(HLength); + inc(offs, 2); + End; + {$ifdef logging2} + LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength)); + {$endif logging} + { offs is now 4-bytes aligned } + If HLength <= (($10000-(Offs and $ffff)) shr 1) Then + bankrest := HLength + else {the rest won't fit anymore in the current window } + bankrest := ($10000 - (Offs and $ffff)) shr 1; + { it is possible that by aligningm we ended up in a new } + { bank, so set the correct bank again to make sure } + setwritebank(offs shr 16); + setreadbank(offs shr 16); + {$ifdef logging2} + LogLn('Rest to be drawn in this window: '+strf(bankrest)); + {$endif logging} + For l := 0 to (Bankrest div 2)-1 Do + MemL[WinWriteSeg:word(offs)+l*4] := + MemL[WinReadSeg:word(offs)+l*4] And Mask; + inc(offs,l*4+4); + dec(hlength,l*2+2); + {$ifdef logging2} + LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength)); + {$endif logging} + End + Else + Begin + {$ifdef logging2} + LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8)); + {$endif logging} + if HLength > 0 then + begin + { this may cross a bank at any time, so adjust } + { because this loop always runs for very little pixels, } + { there's little gained by splitting it up } + setreadbank(offs shr 16); + setwritebank(offs shr 16); + MemW[WinWriteSeg:word(offs)] := + MemW[WinReadSeg:word(offs)] And Word(currentColor); + HLength := 0 + end; + End + Until HLength = 0; + End; + XorPut: + Begin + Repeat + curbank := smallint(offs shr 16); + SetWriteBank(curbank); + SetReadBank(curbank); + {$ifdef logging2} + LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8)); + {$endif logging2} + If ((HLength >= 2) and + ((offs and 3) = 0)) or + (HLength >= 3) Then + { align target } + Begin + If (offs and 3) <> 0 then + { this cannot go past a window boundary because the } + { size of a window is always a multiple of 4 } + Begin + {$ifdef logging2} + LogLn('Aligning by drawing 1 pixel'); + {$endif logging2} + MemW[WinWriteSeg:word(offs)] := + MemW[WinReadSeg:word(offs)] Xor Word(CurrentColor); + Dec(HLength); + inc(offs, 2); + End; + {$ifdef logging2} + LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength)); + {$endif logging} + { offs is now 4-bytes aligned } + If HLength <= (($10000-(Offs and $ffff)) shr 1) Then + bankrest := HLength + else {the rest won't fit anymore in the current window } + bankrest := ($10000 - (Offs and $ffff)) shr 1; + { it is possible that by aligningm we ended up in a new } + { bank, so set the correct bank again to make sure } + setwritebank(offs shr 16); + setreadbank(offs shr 16); + {$ifdef logging2} + LogLn('Rest to be drawn in this window: '+strf(bankrest)); + {$endif logging} + For l := 0 to (Bankrest div 2)-1 Do + MemL[WinWriteSeg:word(offs)+l*4] := + MemL[WinReadSeg:word(offs)+l*4] Xor Mask; + inc(offs,l*4+4); + dec(hlength,l*2+2); + {$ifdef logging2} + LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength)); + {$endif logging} + End + Else + Begin + {$ifdef logging2} + LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8)); + {$endif logging} + if HLength > 0 then + begin + { this may cross a bank at any time, so adjust } + { because this loop always runs for very little pixels, } + { there's little gained by splitting it up } + setreadbank(offs shr 16); + setwritebank(offs shr 16); + MemW[WinWriteSeg:word(offs)] := + MemW[WinReadSeg:word(offs)] Xor Word(currentColor); + HLength := 0 + end; + End + Until HLength = 0; + End; + OrPut: + Begin + Repeat + curbank := smallint(offs shr 16); + SetWriteBank(curbank); + SetReadBank(curbank); + {$ifdef logging2} + LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8)); + {$endif logging2} + If ((HLength >= 2) and + ((offs and 3) = 0)) or + (HLength >= 3) Then + { align target } + Begin + If (offs and 3) <> 0 then + { this cannot go past a window boundary because the } + { size of a window is always a multiple of 4 } + Begin + {$ifdef logging2} + LogLn('Aligning by drawing 1 pixel'); + {$endif logging2} + MemW[WinWriteSeg:word(offs)] := + MemW[WinReadSeg:word(offs)] Or Word(CurrentColor); + Dec(HLength); + inc(offs, 2); + End; + {$ifdef logging2} + LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength)); + {$endif logging} + { offs is now 4-bytes aligned } + If HLength <= (($10000-(Offs and $ffff)) shr 1) Then + bankrest := HLength + else {the rest won't fit anymore in the current window } + bankrest := ($10000 - (Offs and $ffff)) shr 1; + { it is possible that by aligningm we ended up in a new } + { bank, so set the correct bank again to make sure } + setwritebank(offs shr 16); + setreadbank(offs shr 16); + {$ifdef logging2} + LogLn('Rest to be drawn in this window: '+strf(bankrest)); + {$endif logging} + For l := 0 to (Bankrest div 2)-1 Do + MemL[WinWriteSeg:word(offs)+l*4] := + MemL[WinReadSeg:word(offs)+l*4] Or Mask; + inc(offs,l*4+4); + dec(hlength,l*2+2); + {$ifdef logging2} + LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength)); + {$endif logging} + End + Else + Begin + {$ifdef logging2} + LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8)); + {$endif logging} + if HLength > 0 then + begin + { this may cross a bank at any time, so adjust } + { because this loop always runs for very little pixels, } + { there's little gained by splitting it up } + setreadbank(offs shr 16); + setwritebank(offs shr 16); + MemW[WinWriteSeg:word(offs)] := + MemW[WinReadSeg:word(offs)] Or Word(currentColor); + HLength := 0 + end; + End + Until HLength = 0; + End + Else + Begin + If CurrentWriteMode = NotPut Then + Mask := Not(Mask); + Repeat + curbank := smallint(offs shr 16); + SetWriteBank(curbank); + SetReadBank(curbank); + {$ifdef logging2} + LogLn('set bank '+strf(curbank)+' for offset '+hexstr(offs,8)); + {$endif logging2} + If ((HLength >= 2) and + ((offs and 3) = 0)) or + (HLength >= 3) Then + { align target } + Begin + If (offs and 3) <> 0 then + { this cannot go past a window boundary because the } + { size of a window is always a multiple of 4 } + Begin + {$ifdef logging2} + LogLn('Aligning by drawing 1 pixel'); + {$endif logging2} + MemW[WinWriteSeg:word(offs)] := Word(Mask); + Dec(HLength); + inc(offs, 2); + End; + {$ifdef logging2} + LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength)); + {$endif logging} + { offs is now 4-bytes aligned } + If HLength <= (($10000-(Offs and $ffff)) shr 1) Then + bankrest := HLength + else {the rest won't fit anymore in the current window } + bankrest := ($10000 - (Offs and $ffff)) shr 1; + { it is possible that by aligningm we ended up in a new } + { bank, so set the correct bank again to make sure } + setwritebank(offs shr 16); + setreadbank(offs shr 16); + {$ifdef logging2} + LogLn('Rest to be drawn in this window: '+strf(bankrest)); + {$endif logging} + For l := 0 to (Bankrest div 2)-1 Do + MemL[WinWriteSeg:word(offs)+l*4] := Mask; + inc(offs,l*4+4); + dec(hlength,l*2+2); + {$ifdef logging2} + LogLn('Offset is now '+hexstr(offs,8)+', length left: '+strf(hlength)); + {$endif logging} + End + Else + Begin + {$ifdef logging2} + LogLn('Drawing leftover: '+strf(HLength)+' at offset '+hexstr(offs,8)); + {$endif logging} + if HLength > 0 then + begin + { this may cross a bank at any time, so adjust } + { because this loop always runs for very little pixels, } + { there's little gained by splitting it up } + setreadbank(offs shr 16); + setwritebank(offs shr 16); + MemW[WinWriteSeg:word(offs)] := Word(Mask); + HLength := 0 + end; + End + Until HLength = 0; + End; + End; + end; + end; + {$ifdef FPC} {************************************************************************} {* 15/16bit pixels VESA mode routines Linear mode *}