<> <> <> <> <<>> DIRECTORY DragonBitBlt, DragOpsCross, DragOpsCrossUtils, Basics, CountedVM, FunctionCache, PrincOps, PrincOpsUtils, VM, SampleMapOps, SlowSampleMapOps; DragonSampleMapOpsImpl: CEDAR MONITOR IMPORTS DragonBitBlt, DragOpsCrossUtils, Basics, CountedVM, FunctionCache, PrincOpsUtils, VM, SampleMapOps EXPORTS SlowSampleMapOps ~ BEGIN bitsPerWord: NAT ~ Basics.bitsPerWord; Buffer: TYPE ~ SampleMapOps.Buffer; BufferRep: TYPE ~ SampleMapOps.BufferRep; maxCount: NAT ~ SampleMapOps.maxCount; CVEC: TYPE ~ SampleMapOps.CVEC; Function: TYPE ~ SampleMapOps.Function; nullFunction: Function ~ SampleMapOps.nullFunction; lastCVEC: CVEC ~ SampleMapOps.lastCVEC; logBitsPerWord: NAT ~ Basics.logBitsPerWord; SampleMap: TYPE ~ SampleMapOps.SampleMap; SampleMapRep: TYPE ~ SampleMapOps.SampleMapRep; SubMap: TYPE ~ SampleMapOps.SubMap; seedWord: WORD _ 123456B; BITAND: PROC [a, b: CARDINAL] RETURNS [CARDINAL] ~ INLINE {RETURN[Basics.BITAND[a, b]]}; Shift: PROC [a: CARDINAL, b: INTEGER] RETURNS [CARDINAL] ~ INLINE {RETURN[Basics.BITSHIFT[a, b]]}; Check: PROC[x: CARDINAL, max: NAT] RETURNS [NAT] ~ TRUSTED MACHINE CODE { PrincOps.zINC; PrincOps.zBNDCK }; <> IsPowerOfTwo: PROC [c: CARDINAL] RETURNS [BOOLEAN] ~ INLINE { RETURN [BITAND[c, c-1] = 0] }; WordCountFromBit: PROC [bitCount: LONG CARDINAL] RETURNS [LONG CARDINAL] ~ { RETURN [Basics.DoubleShiftRight[[lc[bitCount+(bitsPerWord-1)]], logBitsPerWord].lc] }; Lg: PROC [a: NAT] RETURNS [lg: NAT _ 0] ~ { b: CARDINAL _ 1; UNTIL b >= a DO lg _ lg + 1; b _ b*2; ENDLOOP; }; RoundUp: PROC [a: NAT] RETURNS [x: NAT] ~ INLINE { <> x _ BITAND[a+(DragOpsCross.bitsPerWord-1), CARDINAL.LAST-(DragOpsCross.bitsPerWord-1)]; }; ConvertToDragonBitAddress: PROC[ba: PrincOps.BitAddress] RETURNS[da: DragonBitBlt.DragonBitAddress] = TRUSTED { da.word _ LOOPHOLE[LOOPHOLE[ba.word, INT]/2, DragonBitBlt.DragonPointer]; da.bit _ ba.bit; IF Basics.BITAND[LOOPHOLE[ba.word, Basics.LongNumber].lo, 1B] = 0 THEN RETURN; da.bit _ da.bit + bitsPerWord; }; SpecialConvertToDragonBitAddress: PROC[ba: PrincOps.BitAddress] RETURNS[da: DragonBitBlt.DragonBitAddress] = TRUSTED { <> da.word _ LOOPHOLE[LOOPHOLE[ba.word, INT]/2, DragonBitBlt.DragonPointer]; da.bit _ ba.bit; IF Basics.BITAND[LOOPHOLE[ba.word, Basics.LongNumber].lo, 1B] = 0 THEN RETURN; da.word _ LOOPHOLE[da.word+1]; }; DstFunc: PROC[function: Function] RETURNS[dstFunc: DragonBitBlt.DstFunc] = { SELECT function.dstFunc FROM null => dstFunc _ null; and => dstFunc _ and; or => dstFunc _ or; xor => dstFunc _ xor; ENDCASE => NULL; }; SrcFunc: PROC[function: Function] RETURNS[srcFunc: DragonBitBlt.SrcFunc] = { srcFunc _ IF function.srcFunc = null THEN null ELSE complement; }; smallSize: NAT _ 511; WordSeqRep: TYPE ~ RECORD [SEQUENCE length: NAT OF WORD]; Create: PUBLIC PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord]] RETURNS [s: SampleMap] ~ { RETURN[CreateSampleMap[sSize, fSize, bitsPerSample, none]] }; CreateZ: PUBLIC PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord]] RETURNS [s: SampleMap] ~ { RETURN[CreateSampleMap[sSize, fSize, bitsPerSample, zeros]] }; CreateO: PUBLIC PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord]] RETURNS [s: SampleMap] ~ { RETURN[CreateSampleMap[sSize, fSize, bitsPerSample, ones]] }; HowToInit: TYPE = {none, zeros, ones}; CreateSampleMap: PROC [ sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord], how: HowToInit] RETURNS [s: SampleMap] ~ { bitsPerLine: NAT ~ RoundUp[Basics.LongMult[fSize, bitsPerSample]]; nWords: LONG CARDINAL ~ Basics.LongMult[sSize, bitsPerLine/bitsPerWord]; <> <> <> << s _ UnsafeCreate[>> <> <> <> <> <> <> <> <<];>> <<}>> <> <> <> <> <> <> <> <<];>> <<};>> vm: CountedVM.Handle ~ Allocate[nWords]; TRUSTED { s _ UnsafeCreate[ sSize: sSize, fSize: fSize, bitsPerSample: bitsPerSample, bitsPerLine: bitsPerLine, base: [word: vm.pointer, bit: 0], nWords: vm.words, ref: vm ]; }; <> TRUSTED { lp: LONG POINTER TO WORD _ LOOPHOLE[s.base.word]; initVal: WORD; SELECT how FROM none => initVal _ seedWord; zeros => initVal _ 0; ones => initVal _ 177777B; ENDCASE => initVal _ seedWord; FOR i: LONG CARDINAL IN [0..nWords) DO IF how # none THEN lp^ _ initVal ELSE IF lp^ = 0 THEN lp^ _ initVal _ Basics.BITNOT[initVal]; lp _ LOOPHOLE[lp + 1]; ENDLOOP; }; }; Allocate: PROC [nWords: LONG CARDINAL] RETURNS [vm: CountedVM.Handle _ NIL] ~ { nWords _ MAX[nWords, 256]; vm _ CountedVM.SimpleAllocate[nWords ! VM.CantAllocate => CONTINUE]; IF vm = NIL THEN { <> cache: FunctionCache.Cache ~ FunctionCache.GlobalCache[]; info: FunctionCache.CacheInfo ~ FunctionCache.GetInfo[cache]; FunctionCache.SetLimits[cache, 0, 0]; FunctionCache.SetLimits[x: cache, maxEntries: info.maxEntries, maxTotalSize: info.maxTotalSize]; vm _ CountedVM.SimpleAllocate[nWords]; }; }; Copy: PUBLIC PROC [subMap: SubMap] RETURNS [SampleMap] ~ { s: SampleMap ~ subMap.sampleMap; sMin: NAT ~ Check[subMap.start.s, s.sSize]; fMin: NAT ~ Check[subMap.start.f, s.fSize]; sSize: NAT ~ MIN[subMap.size.s, LOOPHOLE[s.sSize-sMin, NAT]]; fSize: NAT ~ MIN[subMap.size.f, LOOPHOLE[s.fSize-fMin, NAT]]; new: SampleMap ~ CreateO[sSize: sSize, fSize: fSize, bitsPerSample: s.bitsPerSample]; Transfer[dest: new, destStart: [0, 0], source: subMap, function: [null, null], goodDest: NIL]; RETURN [new]; }; DoubleCopy: PUBLIC PROC [to, slowTo, from: SampleMap, destStart: CVEC] = { SampleMapOps.Transfer[dest: to, destStart: destStart, source: [from], function: [null, null]]; Transfer[dest: slowTo, destStart: destStart, source: [from], function: [null, null], goodDest: to]; }; ComputeWords: PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..bitsPerWord]] RETURNS [LONG CARDINAL] ~ { bitsPerLine: NAT ~ RoundUp[Basics.LongMult[fSize, bitsPerSample]]; RETURN [Basics.LongMult[sSize, bitsPerLine/bitsPerWord]] }; nullBitBltTable: DragonBitBlt.BitBltTable ~ [ dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: [] ]; disjointBitBltTable: DragonBitBlt.BitBltTable ~ [ dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: [disjoint: TRUE, disjointItems: TRUE] ]; grayBitBltTable: DragonBitBlt.BitBltTable ~ [ dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: [disjoint: TRUE, disjointItems: TRUE, gray: TRUE] ]; UnsafeCreate: PUBLIC UNSAFE PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord], bitsPerLine: NAT, base: PrincOps.BitAddress, nWords: LONG CARDINAL, ref: REF, scratchDescriptor: SampleMap _ NIL] RETURNS [SampleMap] ~ { dataBitsPerLine: LONG CARDINAL ~ Basics.LongMult[fSize, bitsPerSample]; fillBits: NAT ~ bitsPerLine-dataBitsPerLine; totalBits: LONG CARDINAL ~ Basics.LongMult[sSize, bitsPerLine]-fillBits+base.bit; wrds: LONG CARDINAL ~ WordCountFromBit[totalBits]; check: BOOL[FALSE..FALSE] ~ (nWords < wrds); s: SampleMap ~ IF scratchDescriptor#NIL THEN scratchDescriptor ELSE NEW[SampleMapRep]; s^ _ [ sSize: sSize, fSize: fSize, bitsPerSample: bitsPerSample, base: base, bitsPerLine: bitsPerLine, ref: ref ]; RETURN [s]; }; GetSample: PUBLIC PROC [sampleMap: SampleMap, index: CVEC] RETURNS [CARDINAL] ~ TRUSTED { s: CARDINAL ~ Basics.BoundsCheck[index.s, sampleMap.sSize]; f: CARDINAL ~ Basics.BoundsCheck[index.f, sampleMap.fSize]; bitsPerSample: NAT ~ sampleMap.bitsPerSample; bitIndex: LONG CARDINAL ~ sampleMap.base.bit + Basics.LongMult[s, sampleMap.bitsPerLine] + Basics.LongMult[f, bitsPerSample]; bitAddress: PrincOps.BitAddress ~ IndexBit[sampleMap.base.word, [lc[bitIndex]]]; pointer: LONG POINTER TO ARRAY [0..1] OF WORD ~ bitAddress.word; shiftAmt: INTEGER ~ bitAddress.bit + bitsPerSample - bitsPerWord; mask: CARDINAL ~ Shift[1, bitsPerSample]-1; shiftedBits: CARDINAL ~ IF shiftAmt <= 0 THEN Shift[pointer^[0], shiftAmt] ELSE Shift[pointer^[0], shiftAmt] + Shift[pointer^[1], shiftAmt-16]; RETURN [BITAND[shiftedBits, mask]] }; PutSample: PUBLIC PROC [sampleMap: SampleMap, index: CVEC, value: CARDINAL, function: Function, goodDest: SampleMap] ~ TRUSTED { s: CARDINAL ~ Basics.BoundsCheck[index.s, sampleMap.sSize]; f: CARDINAL ~ Basics.BoundsCheck[index.f, sampleMap.fSize]; bitsPerSample: NAT ~ sampleMap.bitsPerSample; bitIndex: LONG CARDINAL ~ sampleMap.base.bit + Basics.LongMult[s, sampleMap.bitsPerLine] + Basics.LongMult[f, bitsPerSample]; bbPtr: DragonBitBlt.BitBltTable; bb: DragonBitBlt.BitBltTablePtr _ @bbPtr; bb^ _ [ dst: ConvertToDragonBitAddress[IndexBit[sampleMap.base.word, [lc[bitIndex]]]], dstBpl: 0, src: ConvertToDragonBitAddress[[word: @value, bit: bitsPerWord-bitsPerSample]], srcDesc: [srcBpl[0]], height: 1, width: bitsPerSample, flags: [direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: FALSE, srcFunc: SrcFunc[function], dstFunc: DstFunc[function]] ]; DragonBitBlt.BITBLT[bb]; }; DumbTransfer: PROC [dest: SampleMap, destStart: CVEC, source: SubMap, function: Function, goodDest: SampleMap] ~ { sSize: NAT ~ MIN[source.size.s, dest.sSize-destStart.s, source.sampleMap.sSize-source.start.s]; fSize: NAT ~ MIN[source.size.f, dest.fSize-destStart.f, source.sampleMap.fSize-source.start.f]; FOR s: NAT IN [0..sSize) DO FOR f: NAT IN [0..fSize) DO sample: CARDINAL ~ GetSample[source.sampleMap, [source.start.s+s, source.start.f+f]]; PutSample[dest, [destStart.s+s, destStart.f+f], sample, function, goodDest]; ENDLOOP; ENDLOOP; }; BitAddressOverlay: TYPE ~ MACHINE DEPENDENT RECORD [ <> SELECT OVERLAID * FROM ba => [bitAddress: PrincOps.BitAddress], ov => [pointer: LONG POINTER, offset: CARDINAL], ENDCASE ]; IndexBit: UNSAFE PROC [pointer: LONG POINTER, bitOffset: Basics.LongNumber] RETURNS [PrincOps.BitAddress] ~ UNCHECKED INLINE { addr: BitAddressOverlay ~ [ov[ pointer: pointer + Basics.DoubleShiftRight[bitOffset, logBitsPerWord].lc, offset: bitOffset.lo MOD bitsPerWord ]]; RETURN [addr.bitAddress] }; Transfer: PUBLIC PROC [dest: SampleMap, destStart: CVEC, source: SubMap, function: Function, goodDest: SampleMap] ~ TRUSTED { bps: NAT ~ dest.bitsPerSample; src: SampleMap ~ source.sampleMap; sSize: NAT ~ MIN[source.size.s, dest.sSize-destStart.s, source.sampleMap.sSize-source.start.s]; fSize: NAT ~ MIN[source.size.f, src.fSize-source.start.f, dest.fSize-destStart.f]; SELECT TRUE FROM source.sampleMap.bitsPerSample = bps => { bbPtr: DragonBitBlt.BitBltTable; bb: DragonBitBlt.BitBltTablePtr _ @bbPtr; dstBitIndex: LONG CARDINAL ~ dest.base.bit + Basics.LongMult[Check[destStart.s, dest.sSize], dest.bitsPerLine] + Basics.LongMult[Check[destStart.f, dest.fSize], bps]; srcBitIndex: LONG CARDINAL ~ src.base.bit + Basics.LongMult[Check[source.start.s, src.sSize], src.bitsPerLine] + Basics.LongMult[Check[source.start.f, src.fSize], bps]; bb^ _ disjointBitBltTable; bb.dst _ ConvertToDragonBitAddress[ IndexBit[dest.base.word, [lc[dstBitIndex]]] ]; bb.dstBpl _ dest.bitsPerLine; bb.src _ ConvertToDragonBitAddress[ IndexBit[src.base.word, [lc[srcBitIndex]]] ]; bb.srcDesc _ [srcBpl[src.bitsPerLine]]; bb.height _ sSize; bb.width _ fSize * bps; bb.flags.srcFunc _ SrcFunc[function]; bb.flags.dstFunc _ DstFunc[function]; DragonBitBlt.BITBLT[bb]; }; ENDCASE => DumbTransfer[dest, destStart, source, function, goodDest]; }; Move: PUBLIC PROC [sampleMap: SampleMap, destStart: CVEC, sourceStart: CVEC, size: CVEC, function: Function, goodDest: SampleMap] ~ TRUSTED { bps: NAT ~ sampleMap.bitsPerSample; bpl: NAT ~ sampleMap.bitsPerLine; sSize: NAT ~ sampleMap.sSize; fSize: NAT ~ sampleMap.fSize; bbPtr: DragonBitBlt.BitBltTable; bb: DragonBitBlt.BitBltTablePtr _ @bbPtr; dstBitIndex: LONG CARDINAL _ sampleMap.base.bit + Basics.LongMult[Check[destStart.s, sSize], bpl] + Basics.LongMult[Check[destStart.f, fSize], bps]; srcBitIndex: LONG CARDINAL _ sampleMap.base.bit + Basics.LongMult[Check[sourceStart.s, sSize], bpl] + Basics.LongMult[Check[sourceStart.f, fSize], bps]; sSamples: NAT ~ MIN[size.s, sSize-sourceStart.s, sSize-destStart.s]; fSamples: NAT ~ MIN[size.f, fSize-sourceStart.f, fSize-destStart.f]; bb^ _ disjointBitBltTable; bb.dstBpl _ bpl; bb.srcDesc _ [srcBpl[bpl]]; bb.height _ sSamples; bb.width _ bps * fSamples; bb.flags.srcFunc _ SrcFunc[function]; bb.flags.dstFunc _ DstFunc[function]; IF sSamples > 0 AND (sourceStart.f+fSamples) > destStart.f AND (destStart.f+fSamples) > sourceStart.f AND (sourceStart.s+sSamples) > destStart.s AND (destStart.s+sSamples) > sourceStart.s THEN { bb.flags.disjoint _ FALSE; -- the rectangles overlap IF sourceStart.s=destStart.s THEN bb.flags.disjointItems _ FALSE; -- so do the items IF destStart.s>sourceStart.s OR (destStart.s=sourceStart.s AND destStart.f>sourceStart.f) THEN { -- reverse direction delta: LONG CARDINAL _ Basics.LongMult[sSamples-1, bpl]; bb.flags.direction _ backward; bb.srcDesc.srcBpl _ bb.dstBpl _ -bb.dstBpl; dstBitIndex _ dstBitIndex + delta; srcBitIndex _ srcBitIndex + delta; }; }; bb.dst _ ConvertToDragonBitAddress[ IndexBit[sampleMap.base.word, [lc[dstBitIndex]]] ]; bb.src _ ConvertToDragonBitAddress[ IndexBit[sampleMap.base.word, [lc[srcBitIndex]]] ]; DragonBitBlt.BITBLT[bb]; }; DumbFill: PROC [dest: SubMap, value: CARDINAL, function: Function, goodDest: SubMap] ~ { sSize: NAT ~ MIN[dest.size.s, dest.sampleMap.sSize-dest.start.s]; fSize: NAT ~ MIN[dest.size.f, dest.sampleMap.fSize-dest.start.f]; FOR s: NAT IN [0..sSize) DO FOR f: NAT IN [0..fSize) DO PutSample[dest.sampleMap, [dest.start.s+s, dest.start.f+f], value, function, goodDest.sampleMap]; ENDLOOP; ENDLOOP; }; replicator: ARRAY [0..4] OF CARDINAL ~ [0FFFFH, 05555H, 01111H, 00101H, 00001H]; Fill: PUBLIC PROC [dest: SubMap, value: CARDINAL, function: Function, goodDest: SubMap] ~ { bps: NAT ~ dest.sampleMap.bitsPerSample; IF bitsPerWord MOD bps = 0 THEN TRUSTED { dstBitIndex: LONG CARDINAL ~ dest.sampleMap.base.bit + Basics.LongMult[Check[dest.start.s, dest.sampleMap.sSize], dest.sampleMap.bitsPerLine] + Basics.LongMult[Check[dest.start.f, dest.sampleMap.fSize], bps]; sSize: NAT ~ MIN[dest.size.s, dest.sampleMap.sSize-dest.start.s]; fSize: NAT ~ MIN[dest.size.f, dest.sampleMap.fSize-dest.start.f]; bbPtr: DragonBitBlt.BitBltTable; bb: DragonBitBlt.BitBltTablePtr _ @bbPtr; replicatedPixel: CARDINAL _ BITAND[value, Shift[1, bps]-1] * replicator[Lg[bps]]; <> pixelToUse: ARRAY [0..2] OF DragOpsCross.Half _ ALL[DragOpsCrossUtils.CardToHalf[replicatedPixel]]; <> <> <> <> <<};>> bb^ _ grayBitBltTable; bb.dst _ ConvertToDragonBitAddress[ IndexBit[dest.sampleMap.base.word, [lc[dstBitIndex]]] ]; bb.dstBpl _ dest.sampleMap.bitsPerLine; bb.src _ SpecialConvertToDragonBitAddress[ [word: @pixelToUse, bit: 0] ]; bb.height _ MIN[dest.size.s, dest.sampleMap.sSize-dest.start.s]; bb.width _ bps*MIN[dest.size.f, dest.sampleMap.fSize-dest.start.f]; bb.flags.srcFunc _ SrcFunc[function]; bb.flags.dstFunc _ DstFunc[function]; DragonBitBlt.BITBLT[bb]; } ELSE DumbFill[dest, value, function, goodDest]; }; TileBox: PUBLIC PROC [dest: SampleMap, start: CVEC, size: CVEC, source: SampleMap, s0, f0: INTEGER, phase: NAT, function: Function, goodDest: SampleMap] ~ { boxes: PROC[box: BoxProc] ~ {box[start.s, start.f, start.s+size.s, start.f+size.f]}; TileBoxes[dest, boxes, source, s0, f0, phase, function, goodDest]; }; QR: TYPE ~ RECORD [quotient: INTEGER, remainder: NAT]; DivMod: PROC [n: INTEGER, d: NAT] RETURNS [qr: QR] ~ { <> IF d#1 THEN { nn: Basics.LongNumber _ [li[n]]; qq: Basics.LongNumber _ [lc[0]]; IF nn.li < 0 THEN {nn.highbits _ nn.highbits + d; -- qq.highbits _ CARDINAL.LAST --}; [quotient: qq.lowbits, remainder: qr.remainder] _ Basics.LongDivMod[nn.lc, d]; <> qr.quotient _ LOOPHOLE[qq.lowbits]; } ELSE RETURN [[quotient: n, remainder: 0]]; }; Mod: PROC [n: INT, d: NAT] RETURNS [remainder: NAT] ~ { <> IF d#1 THEN { nn: Basics.LongNumber _ [li[n]]; WHILE nn.li < 0 DO nn.highbits _ nn.highbits + d ENDLOOP; WHILE nn.highbits >= d DO nn.highbits _ nn.highbits - d ENDLOOP; RETURN [Basics.LongDivMod[nn.lc, d].remainder]; } ELSE RETURN [remainder: 0]; }; EnlargedSize: PROC [fSize: NAT, bps: NAT] RETURNS [NAT] ~ { n: CARDINAL ~ ((smallWidth+fSize-1)/fSize+bps-1)/bps; RETURN [Basics.LongMult[n, fSize]] }; smallWidth: NAT _ 128; BoxProc: TYPE ~ SampleMapOps.BoxProc; TileBoxes: PUBLIC PROC [dest: SampleMap, boxes: PROC[BoxProc], source: SampleMap, s0, f0: INTEGER, phase: NAT, function: Function, goodDest: SampleMap] ~ { sSize: NAT ~ dest.sSize; fSize: NAT ~ dest.fSize; bps: NAT ~ dest.bitsPerSample; MacroBrickAction: PROC [scratch: SampleMap] ~ { scratchBoxes: PROC[box: BoxProc] ~ {box[0, 0, scratch.sSize, scratch.fSize]}; GeneralTileBoxes[scratch, scratchBoxes, source, 0, 0, phase, [null, null], NIL]; GeneralTileBoxes[dest, boxes, scratch, s0, f0, phase, function, goodDest]; }; IF bps=source.bitsPerSample AND source.fSize*bps = bitsPerWord AND source.bitsPerLine = bitsPerWord AND source.sSize IN (0..16] AND phase = 0 AND source.base.bit = 0 AND function # [null, complement] THEN TRUSTED { bbPtr: DragonBitBlt.BitBltTable; bb: DragonBitBlt.BitBltTablePtr _ @bbPtr; destBPL: CARDINAL ~ dest.bitsPerLine; easyBox: SAFE PROC [smin, fmin, smax, fmax: CARDINAL] ~ TRUSTED { dstBitIndex: LONG CARDINAL ~ dest.base.bit + Basics.LongMult[Check[smin, smax], destBPL] + Basics.LongMult[Check[fmin, fmax], bps]; yOffset: CARDINAL ~ LOOPHOLE[smin-s0, CARDINAL] MOD source.sSize; bb.dst _ ConvertToDragonBitAddress[ IndexBit[dest.base.word, [lc[dstBitIndex]]] ]; bb.src _ ConvertToDragonBitAddress[ [word: source.base.word+yOffset, bit: LOOPHOLE[fmin-f0, CARDINAL] MOD 16] ]; bb.srcDesc.gray.yOffset _ yOffset; bb.height _ Check[smax, sSize]-smin; bb.width _ Basics.LongMult[Check[fmax, fSize]-fmin, bps]; DragonBitBlt.BITBLT[bb]; }; bb^ _ grayBitBltTable; bb.dstBpl _ dest.bitsPerLine; bb.srcDesc.gray.heightMinusOne _ source.sSize-1; bb.flags.srcFunc _ SrcFunc[function]; bb.flags.dstFunc _ DstFunc[function]; boxes[easyBox]; RETURN }; IF bps#source.bitsPerSample OR source.fSize*bps < MIN[smallWidth, dest.fSize] THEN SampleMapOps.DoWithScratch[sSize: source.sSize, fSize: EnlargedSize[source.fSize, bps], bitsPerSample: bps, action: MacroBrickAction] ELSE GeneralTileBoxes[dest, boxes, source, s0, f0, phase, function, goodDest]; }; QMul: PROC [a: INTEGER, b: CARDINAL] RETURNS [INT] ~ INLINE { IF a >= 0 THEN RETURN [LOOPHOLE[Basics.LongMult[a, b]]] ELSE RETURN [-LOOPHOLE[Basics.LongMult[-a, b], INT]] }; GeneralTileBoxes: PROC [dest: SampleMap, boxes: PROC[BoxProc], source: SampleMap, s0, f0: INTEGER, phase: NAT, function: Function, goodDest: SampleMap] ~ { bps: NAT ~ dest.bitsPerSample; sSize: NAT ~ dest.sSize; fSize: NAT ~ dest.fSize; box: SAFE PROC [smin, fmin, smax, fmax: CARDINAL] ~ TRUSTED { sBrickSize: NAT ~ source.sSize; fBrickSize: NAT ~ source.fSize; qr: QR ~ DivMod[(INTEGER[smin]-s0), sBrickSize]; s: CARDINAL _ smin; sDelta: CARDINAL _ sBrickSize - qr.remainder; fSource: CARDINAL _ Mod[fmin-f0 - QMul[qr.quotient, phase], fBrickSize]; WHILE s < smax DO sBrick: NAT ~ sBrickSize-sDelta; sClipSize: NAT ~ MIN[sBrickSize+s, smax]-s; f: NAT _ fmin; fDelta: NAT _ fBrickSize-fSource; WHILE f < fmax DO IF goodDest = NIL THEN SampleMapOps.Transfer[dest: dest, destStart: [s, f], source: [source, [sBrick, fBrickSize-fDelta], [sClipSize, MIN[fBrickSize+f, fmax]-f]], function: function] ELSE Transfer[dest: dest, destStart: [s, f], source: [source, [sBrick, fBrickSize-fDelta], [sClipSize, MIN[fBrickSize+f, fmax]-f]], function: function, goodDest: goodDest]; f _ f + fDelta; fDelta _ fBrickSize; ENDLOOP; s _ s + sDelta; sDelta _ sBrickSize; WHILE fSource < phase DO fSource _ fSource + fBrickSize ENDLOOP; fSource _ fSource - phase; ENDLOOP; }; boxes[box]; }; Get: PUBLIC PROC [buffer: Buffer, start: NAT _ 0, count: NAT _ maxCount, sampleMap: SampleMap, s, f: NAT _ 0, ds: NAT _ 0, df: NAT _ 1] ~ TRUSTED { size: NAT ~ MIN[count, buffer.length-start]; IF size # 0 THEN { sSize: NAT ~ sampleMap.sSize; fSize: NAT ~ sampleMap.fSize; bpl: NAT ~ sampleMap.bitsPerLine; bps: NAT ~ sampleMap.bitsPerSample; bbPtr: DragonBitBlt.BitBltTable; bb: DragonBitBlt.BitBltTablePtr _ @bbPtr; bufferPointer: LONG POINTER ~ InlineGetPointer[buffer, start, size]; srcBitIndex: LONG CARDINAL _ sampleMap.base.bit + Basics.LongMult[Basics.BoundsCheck[s, sSize], bpl] + Basics.LongMult[Basics.BoundsCheck[f, fSize], bps]; srcBitDelta: NAT ~ Basics.LongMult[ds, bpl] + Basics.LongMult[df, bps]; srcBitSkipDelta: NAT _ srcBitDelta; lgSkip: NAT _ 0; skipMinusOne: NAT _ 0; IF ds > 0 THEN [] _ Basics.BoundsCheck[s+Basics.LongMult[size-1, ds], sSize]; IF df > 0 THEN [] _ Basics.BoundsCheck[f+Basics.LongMult[size-1, df], fSize]; WHILE srcBitSkipDelta <= NAT.LAST/2 AND LOOPHOLE[srcBitSkipDelta, CARDINAL] MOD bitsPerWord # 0 DO srcBitSkipDelta _ srcBitSkipDelta * 2; lgSkip _ lgSkip + 1; ENDLOOP; skipMinusOne _ Shift[1, lgSkip]-1; PrincOpsUtils.LongZero[where: bufferPointer, nwords: size]; bb^ _ disjointBitBltTable; bb.dstBpl _ Shift[bitsPerWord, lgSkip]; bb.srcDesc _ [srcBpl[srcBitSkipDelta]]; bb.width _ bps; FOR i: NAT IN [0..Shift[1, lgSkip]) DO bb.src _ ConvertToDragonBitAddress[ IndexBit[sampleMap.base.word, [lc[srcBitIndex]]] ]; bb.height _ Shift[size-i+skipMinusOne, -lgSkip]; bb.dst _ ConvertToDragonBitAddress[ [word: bufferPointer+i, bit: bitsPerWord-bps] ]; DragonBitBlt.BITBLT[bb]; srcBitIndex _ srcBitIndex + srcBitDelta; ENDLOOP; DragonBitBlt.BITBLT[bb]; }; }; Put: PUBLIC PROC [buffer: Buffer, start: NAT _ 0, count: NAT _ maxCount, sampleMap: SampleMap, s, f: NAT _ 0, ds: NAT _ 0, df: NAT _ 1, function: Function _ nullFunction, goodDest: SampleMap] ~ TRUSTED { size: NAT ~ MIN[count, buffer.length-start]; IF size # 0 THEN { sSize: NAT ~ sampleMap.sSize; fSize: NAT ~ sampleMap.fSize; bpl: NAT ~ sampleMap.bitsPerLine; bps: NAT ~ sampleMap.bitsPerSample; bbPtr: DragonBitBlt.BitBltTable; bb: DragonBitBlt.BitBltTablePtr _ @bbPtr; bufferPointer: LONG POINTER ~ InlineGetPointer[buffer, start, size]; dstBitIndex: LONG CARDINAL _ sampleMap.base.bit + Basics.LongMult[Basics.BoundsCheck[s, sSize], bpl] + Basics.LongMult[Basics.BoundsCheck[f, fSize], bps]; dstBitDelta: NAT _ Basics.LongMult[ds, bpl] + Basics.LongMult[df, bps]; dstBitSkipDelta: NAT _ dstBitDelta; lgSkip: NAT _ 0; skipMinusOne: NAT _ 0; bufferFirst: LONG POINTER _ bufferPointer; IF ds > 0 THEN [] _ Basics.BoundsCheck[s+Basics.LongMult[size-1, ds], sSize]; IF df > 0 THEN [] _ Basics.BoundsCheck[f+Basics.LongMult[size-1, df], fSize]; WHILE dstBitSkipDelta <= NAT.LAST/2 AND LOOPHOLE[dstBitSkipDelta, CARDINAL] MOD bitsPerWord # 0 DO dstBitSkipDelta _ dstBitSkipDelta * 2; lgSkip _ lgSkip + 1; ENDLOOP; skipMinusOne _ Shift[1, lgSkip]-1; bb^ _ disjointBitBltTable; bb.flags.srcFunc _ SrcFunc[function]; bb.flags.dstFunc _ DstFunc[function]; bb.dstBpl _ dstBitSkipDelta; bb.srcDesc _ [srcBpl[Shift[bitsPerWord, lgSkip]]]; bb.width _ bps; FOR i: NAT IN [0..Shift[1, lgSkip]) DO bb.dst _ ConvertToDragonBitAddress[ IndexBit[sampleMap.base.word, [lc[dstBitIndex]]] ]; bb.height _ Shift[size-i+skipMinusOne, -lgSkip]; bb.src _ ConvertToDragonBitAddress[ [word: bufferPointer+i, bit: bitsPerWord-bps] ]; DragonBitBlt.BITBLT[bb]; dstBitIndex _ dstBitIndex + dstBitDelta; ENDLOOP; }; }; Flip: PUBLIC PROC [buffer: Buffer] ~ TRUSTED { size: NAT ~ buffer.length; last: INTEGER ~ size-1; s: LONG POINTER TO Basics.RawWords ~ InlineGetPointer[buffer, 0, size]; k: NAT _ size; FOR j: NAT IN [0..size/2) DO t: CARDINAL _ s[j]; s[j] _ s[k _ k-1]; s[k] _ t; ENDLOOP; }; InlineGetPointer: PROC [buffer: Buffer, start: NAT, count: NAT] RETURNS [LONG POINTER TO Basics.RawWords] ~ TRUSTED INLINE { [] _ Check[start+count, buffer.maxLength]; TRUSTED {RETURN [LOOPHOLE[buffer, LONG POINTER TO Basics.RawWords]+SIZE[BufferRep[start]]]} }; END.