ImagerTerminalExtrasImpl.mesa
This implements control over DCBs and color map for the Dorado color display.
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last Edited by:
Crow — May 25, 1984 12:14:02 pm PDT
DIRECTORY
Basics USING [LowHalf, BITSHIFT, logBitsPerWord, LongMult],
VM USING [Allocate, AddressForPageNumber, wordsPerPage, Pin,
Unpin],
CountedVM USING [Handle],
ColorDisplayHeadDorado USING [RPtr, mcb, rpNIL, ChanCB, ChanCBPtr, first64K,
screenwidth],
ImagerPixelMaps USING [PixelMap],
ImagerDisplay USING [DisplayData],
ImagerDisplayExtras USING [RGBSequence],
Atom USING [PutPropOnList, GetPropFromList],
Terminal USING [Virtual, ColorMode, GetColorMode, SetColor, SetRedMap,
SetGreenMap, SetBlueMap, WaitForBWVerticalRetrace],
ImagerTerminalExtras;
ImagerTerminalExtrasImpl:
CEDAR
PROGRAM
IMPORTS VM, ColorDisplayHeadDorado, Basics, Atom, Terminal
EXPORTS ImagerTerminalExtras
SHARES ColorDisplayHeadDorado
~ BEGIN
PixelMap: TYPE ~ ImagerPixelMaps.PixelMap;
DisplayData: TYPE ~ ImagerDisplay.DisplayData;
ImagerTerminalExtrasError: PUBLIC SIGNAL [reason: ATOM] ~ CODE;
storage, limit: ColorDisplayHeadDorado.RPtr ← ColorDisplayHeadDorado.rpNIL;
marginOffset: CARDINAL;
leftOverBytes: NAT;
SetDCB: PROC [aChannel: BOOLEAN ← TRUE, bitmap: LONG POINTER,
leftMargin, width, height, wordsPerLine, whichLink:
NAT] ~
TRUSTED {
Alloc:
PROC [words:
CARDINAL]
RETURNS [pointer: ColorDisplayHeadDorado.RPtr] ~
TRUSTED{
page, count: INT;
storageTop: ColorDisplayHeadDorado.RPtr ← storage + words;
IF (storage = ColorDisplayHeadDorado.rpNIL)
OR (LOOPHOLE[storageTop, CARDINAL] > LOOPHOLE[limit, CARDINAL])
THEN {
[[page, count]] ← VM.Allocate[count: 1, partition: lowCore, in64K: TRUE];
storage ← LOOPHOLE[Basics.LowHalf[LOOPHOLE[VM.AddressForPageNumber[page]]]];
limit ← storage + VM.wordsPerPage;
};
pointer ← storage;
storage ← storage + words;
};
link: NAT ← 0;
chainPtr, lastPtr:
LONG
POINTER
TO ColorDisplayHeadDorado.ChanCB ← NIL;
Check for color display MCB, then DCB chain
IF ColorDisplayHeadDorado.mcb =
NIL
THEN {
SIGNAL ImagerTerminalExtrasError[$NoColorDisplay]; RETURN[]; };
IF aChannel THEN lastPtr ← chainPtr ←
@ColorDisplayHeadDorado.first64K[ColorDisplayHeadDorado.mcb.achanCB]
ELSE lastPtr ← chainPtr ←
@ColorDisplayHeadDorado.first64K[ColorDisplayHeadDorado.mcb.bchanCB];
IF chainPtr =
NIL
THEN {
SIGNAL ImagerTerminalExtrasError[$NoDCBChain]; RETURN[]; };
IF whichLink > 31 THEN { SIGNAL ImagerTerminalExtrasError[$Over32DCBs]; RETURN[]; };
IF (wordsPerLine * 2 > leftOverBytes)
THEN
-- check for excess leftovers at end of scan
IF (ColorDisplayHeadDorado.screenwidth - width) > leftOverBytes
THEN { SIGNAL ImagerTerminalExtrasError[$ExcessLeftOverPixels]; RETURN[]; };
Find desired link in DCB chain
WHILE (link < whichLink)
AND
NOT (chainPtr = NIL)
DO
link ← link + 1;
lastPtr ← chainPtr; -- step to next link
IF chainPtr.link = ColorDisplayHeadDorado.rpNIL
THEN chainPtr ← NIL
ELSE chainPtr ← @ColorDisplayHeadDorado.first64K[chainPtr.link];
ENDLOOP;
Load desired link; Make new links if desired link lies beyond end of chain
WHILE link <= whichLink
DO
relPtr: ColorDisplayHeadDorado.ChanCBPtr ← ColorDisplayHeadDorado.rpNIL;
IF chainPtr =
NIL
THEN {
-- Make new DCB, if unlinked
relPtr ← Alloc[SIZE[ColorDisplayHeadDorado.ChanCB]];
chainPtr ← @ColorDisplayHeadDorado.first64K[relPtr];
chainPtr.link ← ColorDisplayHeadDorado.rpNIL; -- make sure chain ends here
}
ELSE relPtr ← lastPtr.link; -- in case chain is already linked (or zeroth link)
IF (link < whichLink)
OR (width = 0)
-- null DCB
THEN {
chainPtr.wordsPerLine ← 0;
chainPtr.bitmap ← NIL;
chainPtr.linesPerField ← IF link = whichLink THEN height / 2 ELSE 0;
chainPtr.pixelsPerLine ← 0;
chainPtr.leftMargin ← LAST[NAT];
chainPtr.scan ← lastPtr.scan;
}
ELSE {
chainPtr.wordsPerLine ← wordsPerLine; -- load visible DCB
chainPtr.bitmap ← bitmap;
chainPtr.linesPerField ← height / 2;
chainPtr.pixelsPerLine ← width + 255;
chainPtr.leftMargin ← leftMargin + marginOffset;
chainPtr.scan ← lastPtr.scan;
};
lastPtr.link ← relPtr; -- link into DCB chain after loaded
lastPtr ← chainPtr; -- step to next link
IF chainPtr.link = ColorDisplayHeadDorado.rpNIL
THEN chainPtr ← NIL
ELSE chainPtr ← @ColorDisplayHeadDorado.first64K[chainPtr.link];
link ← link + 1;
ENDLOOP;
};
DeleteDCB:
PROC [aChannel:
BOOLEAN ←
TRUE, whichLink:
NAT] ~
TRUSTED {
link: NAT ← 0;
chainPtr, lastPtr: LONG POINTER TO ColorDisplayHeadDorado.ChanCB ← NIL;
IF ColorDisplayHeadDorado.mcb =
NIL
THEN {
SIGNAL ImagerTerminalExtrasError[$NoColorDisplay]; RETURN[]; };
IF aChannel THEN lastPtr ← chainPtr ←
@ColorDisplayHeadDorado.first64K[ColorDisplayHeadDorado.mcb.achanCB]
ELSE lastPtr ← chainPtr ←
@ColorDisplayHeadDorado.first64K[ColorDisplayHeadDorado.mcb.bchanCB];
IF chainPtr =
NIL
THEN {
SIGNAL ImagerTerminalExtrasError[$NoDCBChain]; RETURN[]; };
Find desired link in DCB chain
WHILE (link < whichLink)
AND
NOT (chainPtr = NIL)
DO
link ← link + 1;
lastPtr ← chainPtr; -- step to next link
IF chainPtr.link = ColorDisplayHeadDorado.rpNIL
THEN chainPtr ← NIL
ELSE chainPtr ← @ColorDisplayHeadDorado.first64K[chainPtr.link];
ENDLOOP;
Delete Link, if found
IF link = whichLink THEN lastPtr.link ← chainPtr.link; -- note, no storage recovery
};
PinPixelMap:
PUBLIC
PROC [vt: Terminal.Virtual, data: DisplayData, overLay:
BOOLEAN ←
FALSE] ~ {
Pin a pixel map to the color display, replacing whatever was there before. Overlay = TRUE causes the B-channel to be used. Overlays may have only 2 or 4 bits per pixel, 4 only if the A-channel (non-overlay) pixelmap has <= 4 bits per pixel.
logPixelsPerWord: NAT ← Basics.logBitsPerWord - data.pix[0].refRep.lgBitsPerPixel;
Catch negative origins and bite into pixelmap
bitmapPtr: LONG POINTER;
widthChange, heightChange: INTEGER ← 0;
TRUSTED {
IF data.pix[0].sOrigin >= 0
THEN bitmapPtr ← data.pix[0].refRep.pointer
ELSE {
bitmapPtr ← data.pix[0].refRep.pointer
+ Basics.LongMult[-data.pix[0].sOrigin, data.pix[0].refRep.rast];
heightChange ← data.pix[0].sOrigin;
};
IF data.pix[0].fOrigin < 0
THEN {
ptrChange: NAT ← Basics.BITSHIFT[
Basics.BITSHIFT[ -data.pix[0].fOrigin, -(logPixelsPerWord+1)],
1];
bitmapPtr ← bitmapPtr + ptrChange;
widthChange ← -Basics.BITSHIFT[ ptrChange, logPixelsPerWord];
};
};
Pin VM pages involved
VM.Pin[
NARROW[data.pix[0].refRep.ref, CountedVM.Handle].interval ];
Set Null DCB to move down proper distance from top of screen
SetDCB[ aChannel: NOT overLay,
bitmap: bitmapPtr,
leftMargin: 0,
width: 0,
height: MAX[0, data.pix[0].sOrigin],
wordsPerLine: 0,
whichLink: 0
];
Set DCB representing pixelmap
SetDCB[ aChannel: NOT overLay,
bitmap: bitmapPtr,
leftMargin: MAX[0, data.pix[0].fOrigin],
width: MAX[0, Basics.BITSHIFT[ data.pix[0].refRep.rast, logPixelsPerWord] + widthChange],
height: MAX[0, data.pix[0].refRep.lines + heightChange],
wordsPerLine: data.pix[0].refRep.rast,
whichLink: 1
];
IF overLay
THEN data.props ← Atom.PutPropOnList[data.props, $PixelMapStatus, $OnAChannel]
ELSE data.props ← Atom.PutPropOnList[data.props, $PixelMapStatus, $OnBChannel];
};
ReleasePixelMap:
PUBLIC
PROC [vt: Terminal.Virtual, data: DisplayData] ~ {
Remove a pixel map from the color display
IF Atom.GetPropFromList[data.props, $PixelMapStatus] = $OnAChannel
THEN { DeleteDCB[TRUE, 1];
data.props ← Atom.PutPropOnList[data.props, $PixelMapStatus, $Allocated];
}
ELSE
IF Atom.GetPropFromList[data.props, $PixelMapStatus] = $OnBChannel
THEN { DeleteDCB[FALSE, 1];
data.props ← Atom.PutPropOnList[data.props, $PixelMapStatus, $Allocated];
}
ELSE SIGNAL ImagerTerminalExtrasError[$UnDisplayedPixelMap];
VM.Unpin[ NARROW[data.pix[0].refRep.ref, CountedVM.Handle].interval ]; -- release storage
};
LoadRGBColorMap: PUBLIC PROC [vt: Terminal.Virtual,
entries:
REF ImagerDisplayExtras.RGBSequence, start:
NAT ← 0] ~ {
mode: Terminal.ColorMode ← vt.GetColorMode;
vt.WaitForBWVerticalRetrace[]; -- await vt selection and top of scan (to control update rate)
IF mode.full = FALSE -- pseudocolor mapped display
THEN IF mode.bitsPerPixelChannelB = 2
-- 4 tables each 256 entries
THEN {
FOR i:
NAT
IN [start..entries.length)
DO
index: NAT ← i MOD 256; table: NAT ← i / 256;
vt.SetColor[index, table, entries[i].r, entries[i].g, entries[i].b];
ENDLOOP; }
ELSE {
FOR i:
NAT
IN [start..entries.length)
DO
-- 16 tables each 16 entries
index: NAT ← i MOD 16; table: NAT ← i / 16;
vt.SetColor[index, table, entries[i].r, entries[i].g, entries[i].b];
ENDLOOP ; }
ELSE
FOR index:
NAT
IN [start..entries.length)
DO
-- full-color 24-bit display
vt.SetRedMap[index, entries[index].r];
vt.SetGreenMap[index, entries[index].g];
vt.SetBlueMap[index, entries[index].b];
ENDLOOP;
};
{
-- initialize: set left margin assuming monitor type from resolution (potentially wrong)
SELECT ColorDisplayHeadDorado.screenwidth
FROM
640 => { marginOffset ← 54;
-- Hitachi 13" monitors, or Conrac @525 lines
leftOverBytes ← 460; }; -- Exceeding this causes unstable raster
1024 => { marginOffset ← 71;
-- Conrac @768 lines (may be 0, actually)
leftOverBytes ← 0; };
ENDCASE;
};
END.