mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-16 17:19:32 +02:00
+ implemented VESA banked 32k/64k colour mode fast line drawing in the go32v2 graph unit
git-svn-id: trunk@30246 -
This commit is contained in:
parent
b617345e43
commit
69d839e891
@ -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);
|
||||
|
@ -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 *}
|
||||
|
Loading…
Reference in New Issue
Block a user