DIRECTORY Real USING [FixC], Inline USING [LongMult], BitBlt USING [AlignedBBTable, BBTableSpace, BITBLT, BitBltTable, BitBltTablePtr], Environment USING [wordsPerPage, bitsPerWord], UserTerminal USING [GetState, SetState, GetBitBltTable, screenWidth, screenHeight, State], Space USING [Handle, Create, virtualMemory, defaultBase, LongPointer, Delete, Map], ImagerBasic USING [Transformation, IntRectangle, IntPair, CIEColor, CIEColorRep, PixelArray, PixelArrayRep], ImagerDisplay USING [ByteSequence, ByteSequenceRep, DisplayProcs, DisplayProcsRec, Mask, MaskRep, VtxSequence], ImagerDisplayPrivate USING [Data1bitPixels, Data1bitPixelsRep], Imager1bitDisplay USING [SetUp, ShutDown, OpenPixelBuffer, ClosePixelBuffer, ColortoPixel, PixeltoColor, HilitePxls, MovePxls, StorePxls, LoadPxls, StoreScanSeg, LoadScanSeg, LoadTrapezoid, SetPxl, GetPxl, DrawLine, Tiler]; Imager1bitDisplayImpl: CEDAR MONITOR IMPORTS Real, Inline, BitBlt, Imager1bitDisplay, Space, UserTerminal EXPORTS Imager1bitDisplay = BEGIN OPEN ImagerBasic, ImagerDisplay; bpPxl: CARDINAL = 1; maxPxlValue: CARDINAL = 1; bpWd: CARDINAL = Environment.bitsPerWord; pxpWd: CARDINAL = bpWd/bpPxl; maxDisplayWidth: CARDINAL = 8192; -- number in excess of maximum expected BITBLT width storage: Space.Handle; -- space for double-buffering swapUnitSize: CARDINAL _ 50; -- unbelieveable crap for getting large spaces pixelBuffer: PixelArray _ NIL; -- ref for double buffering bufferLimits: Mask; nullBitBltTable: BitBlt.BitBltTable = [ dst: [word: NIL, bit: 0], dstBpl: maxDisplayWidth, src: [word: NIL, bit: 0], srcDesc: [srcBpl[maxDisplayWidth]], width: 0, height: 1, flags: [disjoint: TRUE] ]; bbTableForLF: BitBlt.BitBltTable; NotImplementedYet: PUBLIC SIGNAL = CODE; IncompatiblePixelArray: PUBLIC SIGNAL = CODE; SQR: PROCEDURE [number: REAL] RETURNS [REAL] = INLINE { RETURN[number * number]; }; SGN: PROCEDURE [number: INTEGER] RETURNS [INTEGER] = INLINE { IF number >= 0 THEN RETURN[1] ELSE RETURN[-1]; }; GetBufferSpecs: PROCEDURE [place: IntPair] RETURNS [ CARDINAL, LONG POINTER ] = TRUSTED INLINE { wordsPerLine: CARDINAL; pxlPtr: LONG POINTER; IF pixelBuffer = NIL THEN { wordsPerLine _ bbTableForLF.dstBpl/pxpWd; pxlPtr _ LOOPHOLE[ bbTableForLF.dst.word + Inline.LongMult[wordsPerLine, place.y] + (place.x/pxpWd), LONG POINTER]; } ELSE { wordsPerLine _ IF pixelBuffer.xPixels MOD pxpWd = 0 THEN pixelBuffer.xPixels/pxpWd ELSE pixelBuffer.xPixels/pxpWd + 1 ; pxlPtr _ LOOPHOLE[ NARROW[pixelBuffer.data, ImagerDisplayPrivate.Data1bitPixels].p + Inline.LongMult[wordsPerLine, place.y] + (place.x/pxpWd), LONG POINTER]; }; RETURN [ wordsPerLine, pxlPtr ]; }; SetUp: PUBLIC PROC [pin: BOOLEAN _ TRUE] RETURNS [REF Transformation, Mask, DisplayProcs] = TRUSTED { oldState: UserTerminal.State; IF NOT UserTerminal.GetState[] = on THEN oldState _ UserTerminal.SetState[ on ]; bbTableForLF _ UserTerminal.GetBitBltTable[]; RETURN[ NEW [Transformation _ [1., 0., 0., 0., -1., UserTerminal.screenHeight, mirrorY] ], NEW [MaskRep _ [ 1, 1, UserTerminal.screenHeight, UserTerminal.screenWidth - 1, NIL] ], NEW [DisplayProcsRec _ [ setUp: Imager1bitDisplay.SetUp, shutDown: Imager1bitDisplay.ShutDown, openPixelBuffer: Imager1bitDisplay.OpenPixelBuffer, closePixelBuffer: Imager1bitDisplay.ClosePixelBuffer, colortoPixel: Imager1bitDisplay.ColortoPixel, pixeltoColor: Imager1bitDisplay.PixeltoColor, hilitePxls: Imager1bitDisplay.HilitePxls, movePxls: Imager1bitDisplay.MovePxls, storePxls: Imager1bitDisplay.StorePxls, loadPxls: Imager1bitDisplay.LoadPxls, storeScanSeg: Imager1bitDisplay.StoreScanSeg, loadScanSeg: Imager1bitDisplay.LoadScanSeg, loadTrapezoid: Imager1bitDisplay.LoadTrapezoid, setPixel: Imager1bitDisplay.SetPxl, getPixel: Imager1bitDisplay.GetPxl, drawLine: Imager1bitDisplay.DrawLine, tiler: Imager1bitDisplay.Tiler ] ] ]; }; ShutDown: PUBLIC PROC [] = TRUSTED { -- free memory in case the last user has left oldState: UserTerminal.State; oldState _ UserTerminal.SetState[ disconnected ]; }; OpenPixelBuffer: PUBLIC PROC [box: Mask, buffer: PixelArray _ NIL] RETURNS [PixelArray] = TRUSTED { -- redirect writes for double-buffer boxWidth: CARDINAL _ box.fSize; boxHeight: CARDINAL _ box.sSize; IF pixelBuffer # NIL THEN RETURN [pixelBuffer]; -- can't support multiple buffers yet IF buffer = NIL THEN { wordsPerLine: CARDINAL _ IF boxWidth MOD pxpWd = 0 THEN boxWidth/pxpWd ELSE boxWidth/pxpWd + 1; pages: CARDINAL _ (Inline.LongMult[wordsPerLine, boxHeight + 1] / Environment.wordsPerPage) + 1; storage _ Space.Create[ pages, Space.virtualMemory, Space.defaultBase ]; FOR offset: CARDINAL _ 0, offset + swapUnitSize WHILE offset + swapUnitSize <= pages DO -- get space in small pieces [] _ Space.Create[size: swapUnitSize, parent: storage, base: offset] ENDLOOP; Space.Map[storage]; pixelBuffer _ NEW[ PixelArrayRep _ [ xPixels: boxWidth, yPixels: boxHeight, maxSampleValue: maxPxlValue, samplesPerPixel: 1, xDelta: 1, yDelta: wordsPerLine, data: NEW[ ImagerDisplayPrivate.Data1bitPixelsRep _ [ Space.LongPointer[storage] ] ] ] ] } ELSE IF NOT ( buffer.maxSampleValue = maxPxlValue AND buffer.xPixels MOD pxpWd = 0 AND -- Check for integer row length in words ISTYPE [buffer.data, ImagerDisplayPrivate.Data1bitPixels] ) THEN ERROR IncompatiblePixelArray[] ELSE { buffer.xPixels _ boxWidth; buffer.yPixels _ boxHeight; pixelBuffer _ buffer; }; bufferLimits _ box; -- keep limits for translating loads to buffer RETURN [pixelBuffer]; }; ClosePixelBuffer: PUBLIC PROC [] = TRUSTED { IF pixelBuffer = NIL THEN RETURN; Space.Delete[storage]; -- deallocate bit storage pixelBuffer _ NIL; }; ColortoPixel: PUBLIC PROC [color: CIEColor] RETURNS [LONG CARDINAL] = { -- Color to device transform RETURN [ IF color.Y > 0 THEN 0 ELSE LAST[CARDINAL] ]; }; PixeltoColor: PUBLIC PROC [pxlValue: LONG CARDINAL] RETURNS [CIEColor] = TRUSTED { color: CIEColor _ NEW[ CIEColorRep ]; IF pxlValue # 0 THEN pxlValue _ 1; -- bivalued pixels color.x _ Real.FixC[pxlValue * LAST[CARDINAL]]; -- this should be proceeded by a transform color.y _ Real.FixC[pxlValue * LAST[CARDINAL]]; color.Y _ Real.FixC[pxlValue * LAST[CARDINAL]]; RETURN [ color ]; }; HilitePxls: PUBLIC PROC [area: IntRectangle] = { -- Device dependent highlighting scheme }; MovePxls: PUBLIC PROC [source: IntRectangle, destination: IntPair] = TRUSTED { -- move on display bbspace: BitBlt.BBTableSpace; bb: BitBlt.BitBltTablePtr _ BitBlt.AlignedBBTable[@bbspace]; srcPxlPtr, dstPxlPtr: LONG POINTER; wordsPerLine: CARDINAL; [ wordsPerLine, dstPxlPtr ] _ GetBufferSpecs[ destination]; [ wordsPerLine, srcPxlPtr ] _ GetBufferSpecs[ IntPair[source.x, source.y] ]; bb^ _ bbTableForLF; bb.dst.word _ dstPxlPtr; bb.dst.bit _ destination.x MOD pxpWd; bb.src.word _ srcPxlPtr; bb.src.bit _ source.x MOD pxpWd; bb.srcDesc.srcBpl _ bb.dstBpl _ wordsPerLine * bpWd; bb.width _ MIN[source.w, (UserTerminal.screenWidth - destination.x)]; bb.height _ MIN[source.h, UserTerminal.screenHeight - destination.y]; BitBlt.BITBLT[bb]; }; StorePxls: PUBLIC PROC [source: IntRectangle] RETURNS [PixelArray] = { dest: PixelArray _ NEW[ PixelArrayRep ]; RETURN [dest]; }; LoadPxls: PUBLIC PROC [source: PixelArray _ NIL, destination: IntRectangle] = TRUSTED { bbspace: BitBlt.BBTableSpace; bb: BitBlt.BitBltTablePtr _ BitBlt.AlignedBBTable[@bbspace]; IF source = NIL THEN { IF pixelBuffer = NIL THEN RETURN[] -- error return if no buffer ELSE source _ pixelBuffer; } -- default to double buffer ELSE IF NOT ( source.maxSampleValue = maxPxlValue AND source.xPixels MOD pxpWd = 0 AND -- Check for integer row length in words ISTYPE [source.data, ImagerDisplayPrivate.Data1bitPixels] ) THEN ERROR IncompatiblePixelArray[]; -- error return if not BLT-able bb^ _ bbTableForLF; bb.dst.word _ LOOPHOLE[bb.dst.word + Inline.LongMult[bb.dstBpl/pxpWd, destination.y] + (destination.x/pxpWd), LONG POINTER]; bb.dst.bit _ destination.x MOD pxpWd; bb.src.word _ NARROW[source.data, ImagerDisplayPrivate.Data1bitPixels].p; bb.srcDesc.srcBpl _ IF source # pixelBuffer THEN source.xPixels ELSE IF pixelBuffer.xPixels MOD pxpWd = 0 THEN (pixelBuffer.xPixels/pxpWd)*bpWd ELSE (pixelBuffer.xPixels/pxpWd + 1)*bpWd; bb.width _ MIN[source.xPixels, destination.w, UserTerminal.screenWidth - destination.x]; bb.height _ MIN[source.yPixels, destination.h, UserTerminal.screenHeight - destination.y]; BitBlt.BITBLT[bb]; }; StoreScanSeg: PUBLIC PROC [x, y, length: CARDINAL] RETURNS [ByteSequence] = { segment: ByteSequence _ NEW [ ByteSequenceRep[length/pxpWd] ]; RETURN [segment]; }; LoadScanSeg: PUBLIC PROC [x, y, length: CARDINAL, segment: ByteSequence, transparent: BOOLEAN] = TRUSTED { bbspace: BitBlt.BBTableSpace; bb: BitBlt.BitBltTablePtr _ BitBlt.AlignedBBTable[@bbspace]; pxlPtr: LONG POINTER; wordsPerLine: CARDINAL; IF pixelBuffer # NIL THEN { x _ x - bufferLimits.fMin; y _ y - bufferLimits.sMin; }; [wordsPerLine, pxlPtr] _ GetBufferSpecs[ [x, y] ]; bb^ _ nullBitBltTable; bb.dst.word _ pxlPtr; bb.dst.bit _ x MOD pxpWd; bb.src.word _ LOOPHOLE[segment, LONG POINTER]; bb.width _ length; BitBlt.BITBLT[bb]; }; LoadTrapezoid: PUBLIC PROC [top, bottom, leftTop, leftBot, rightTop, rightBot: CARDINAL, pxlValue: LONG CARDINAL] = TRUSTED { -- Scan convert trapezoid, constant color bbspace: BitBlt.BBTableSpace; bb: BitBlt.BitBltTablePtr _ BitBlt.AlignedBBTable[@bbspace]; pxlPtr: LONG POINTER; color: CARDINAL; wordsPerLine: CARDINAL; IF pixelBuffer # NIL THEN { -- adjust for buffer limits top _ top - bufferLimits.sMin; bottom _ bottom - bufferLimits.sMin; leftTop _ leftTop - bufferLimits.fMin; leftBot _ leftBot - bufferLimits.fMin; rightTop _ rightTop - bufferLimits.fMin; rightBot _ rightBot - bufferLimits.fMin; }; [wordsPerLine, pxlPtr] _ GetBufferSpecs[ [leftTop, bottom] ]; IF leftTop = leftBot AND rightTop = rightBot THEN { -- rectangle color _ IF pxlValue # 0 THEN LAST[CARDINAL] ELSE 0; -- make brick for BitBlt bb^ _ nullBitBltTable; bb.flags.gray _ TRUE; bb.dstBpl _ wordsPerLine * bpWd; bb.dst.word _ pxlPtr; bb.dst.bit _ leftBot MOD pxpWd; bb.src.word _ @color; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 15, heightMinusOne: 0]; bb.width _ MIN[rightBot - leftBot + 1, UserTerminal.screenWidth - leftBot]; bb.height _ MIN[top - bottom + 1, UserTerminal.screenHeight - bottom]; BitBlt.BITBLT[bb]; } ELSE { -- not rectangle }; }; SetPxl: PUBLIC PROC [x, y: CARDINAL, pxlValue: LONG CARDINAL] = TRUSTED { wordsPerLine: CARDINAL; pxlPtr: LONG POINTER TO PACKED ARRAY [0..16) OF BOOLEAN; [wordsPerLine, LOOPHOLE[pxlPtr, LONG POINTER]] _ GetBufferSpecs[ [x, y] ]; pxlPtr[x MOD pxpWd] _ IF pxlValue # 0 THEN TRUE ELSE FALSE; }; GetPxl: PUBLIC PROC [x, y: CARDINAL] RETURNS [LONG CARDINAL] = TRUSTED { wordsPerLine: CARDINAL; pxlPtr: LONG POINTER TO PACKED ARRAY [0..16) OF BOOLEAN; [wordsPerLine, LOOPHOLE[pxlPtr, LONG POINTER]] _ GetBufferSpecs[ [x, y] ]; RETURN [ IF pxlPtr[x MOD pxpWd] THEN 1 ELSE 0 ]; }; DrawLine: PUBLIC PROC [a, b: IntPair, pxlValue: LONG CARDINAL] = TRUSTED { -- fast line, constant color increment, bias, error, yBump: INTEGER; bit: [0..pxpWd); t: IntPair; wordsPerLine: CARDINAL; bitValue: BOOLEAN; pxlPtr: LONG POINTER TO PACKED ARRAY [0..16) OF BOOLEAN; IF pixelBuffer # NIL THEN { -- adjust for buffer limits a.x _ a.x - bufferLimits.fMin; a.y _ a.y - bufferLimits.sMin; b.x _ b.x - bufferLimits.fMin; b.y _ b.y - bufferLimits.sMin; }; IF a.x > b.x THEN { t _ a; a _ b; b _ t; }; -- make sure of positive-going x bitValue _ IF pxlValue # 0 THEN FALSE ELSE TRUE; [wordsPerLine, LOOPHOLE[pxlPtr, LONG POINTER]] _ GetBufferSpecs[ a ]; IF (b.x - a.x) > ABS[b.y - a.y] THEN { -- more horizontal line increment _ 2 * (b.y - a.y); bias _ 2 * (b.x - a.x); yBump _ SGN[increment] * wordsPerLine; increment _ ABS[increment]; bias _ ABS[bias]; error _ increment - bias/2; bit _ a.x MOD pxpWd; FOR i: CARDINAL IN [0..ABS[b.x-a.x]] DO pxlPtr[bit] _ bitValue; IF bit = (pxpWd - 1) THEN { pxlPtr _ pxlPtr + 1; bit _ 0 } ELSE bit _ bit + 1; IF error > 0 THEN { pxlPtr _ pxlPtr + yBump; error _ error - bias; }; error _ error + increment; ENDLOOP; } ELSE { -- more vertical line increment _ 2 * (b.x - a.x); bias _ 2 * (b.y - a.y); yBump _ SGN[bias] * wordsPerLine; increment _ ABS[increment]; bias _ ABS[bias]; error _ increment - bias/2; bit _ a.x MOD pxpWd; FOR i: CARDINAL IN [0..ABS[b.y-a.y]] DO pxlPtr[bit] _ bitValue; pxlPtr _ pxlPtr + yBump; IF error > 0 THEN { error _ error - bias; IF bit = (pxpWd - 1) THEN { pxlPtr _ pxlPtr + 1; bit _ 0 } ELSE bit _ bit + 1; }; error _ error + increment; ENDLOOP; }; }; Tiler: PUBLIC PROC [vtxCount: CARDINAL, vertices: VtxSequence] = { }; END. ์Imager1bitDisplayImpl.mesa This implements the low level routines for the LF display. Last Edited by: Crow, August 1, 1983 3:38 pm get memory, pin it, set the transform and clipper Using a slightly modified Bresenham's algorithm ส•˜headšœ™J™:—™šœ™Jšœ™—unitšฯk ˜ Jšœœ˜Jšœ œ ˜Jšœ œ œ˜TJšœ œ˜/Jšœ œH˜ZJšœ œB˜PJšœ ˜ Jšœœ(˜;Jšœ;˜;Jšœœ?˜RJšœ$˜$Jšœœ%˜?Jšœœ5˜LJšœE˜EJšœD˜DJšœ"˜"——head2šœ$˜$Jšœ=˜DJšœ˜Lšœ˜Lšœ˜ J˜Jšœœ˜Jšœ œ˜Jšœœ˜)Jšœœ˜Jšœœ ฯc4˜WLšœž˜7Lšœœž.˜ULšœœž˜˜AJšœ.˜.Jšœ:˜:Jšœ<˜Jšœ ˜—Jšœ˜š Ÿ œœœœ'œœ˜kJšœ˜Jšœ<˜