DIRECTORY BitBltOps, Basics, CountedVM, FunctionCache, PrincOps, PrincOpsUtils, VM, SampleMapOps, SlowSampleMapOps; SlowSampleMapOpsImpl: CEDAR MONITOR IMPORTS BitBltOps, 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; dragonBitsPerWord: CARDINAL = 32; useDragonBitsPerWord: BOOL _ TRUE; 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 [NAT] ~ INLINE { IF useDragonBitsPerWord THEN RETURN [BITAND[a+(dragonBitsPerWord-1), CARDINAL.LAST-(dragonBitsPerWord-1)]] ELSE RETURN [BITAND[a+(bitsPerWord-1), CARDINAL.LAST-(bitsPerWord-1)]] }; 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]; IF nWords <= smallSize THEN TRUSTED { words: NAT _ MAX[NAT[nWords], 1]; wordSeq: REF WordSeqRep _ NEW[WordSeqRep[words]]; s _ UnsafeCreate[ sSize: sSize, fSize: fSize, bitsPerSample: bitsPerSample, bitsPerLine: bitsPerLine, base: [word: @wordSeq[0], bit: 0], nWords: words, ref: wordSeq ]; } ELSE TRUSTED { vm: CountedVM.Handle ~ Allocate[nWords]; 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: PrincOps.BitBltTable ~ [ dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: [] ]; disjointBitBltTable: PrincOps.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: PrincOps.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]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bb^ _ [ dst: IndexBit[sampleMap.base.word, [lc[bitIndex]]], dstBpl: 0, src: [word: @value, bit: bitsPerWord-bitsPerSample], srcDesc: [srcBpl[0]], height: 1, width: bitsPerSample, flags: [direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: FALSE, srcFunc: function.srcFunc, dstFunc: function.dstFunc] ]; IF goodDest = NIL THEN BitBltOps.BitBltOp[bb] ELSE BitBltOps.BitBltOpCheck[bb, IndexBit[goodDest.base.word, [lc[bitIndex]]] ]; }; 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 => { bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; 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 _ IndexBit[dest.base.word, [lc[dstBitIndex]]]; bb.dstBpl _ dest.bitsPerLine; bb.src _ IndexBit[src.base.word, [lc[srcBitIndex]]]; bb.srcDesc _ [srcBpl[src.bitsPerLine]]; bb.height _ sSize; bb.width _ fSize * bps; bb.flags.srcFunc _ function.srcFunc; bb.flags.dstFunc _ function.dstFunc; IF goodDest = NIL THEN BitBltOps.BitBltOp[bb] ELSE BitBltOps.BitBltOpCheck[bb, IndexBit[goodDest.base.word, [lc[dstBitIndex]]] ]; }; 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; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; 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 _ function.srcFunc; bb.flags.dstFunc _ function.dstFunc; 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 _ IndexBit[sampleMap.base.word, [lc[dstBitIndex]]]; bb.src _ IndexBit[sampleMap.base.word, [lc[srcBitIndex]]]; IF goodDest = NIL THEN BitBltOps.BitBltOp[bb] ELSE BitBltOps.BitBltOpCheck[bb, IndexBit[goodDest.base.word, [lc[dstBitIndex]]] ]; }; 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]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; replicatedPixel: CARDINAL _ BITAND[value, Shift[1, bps]-1] * replicator[Lg[bps]]; IF function = [null, complement] THEN { replicatedPixel _ CARDINAL.LAST-replicatedPixel; function _ [null, null]; }; bb^ _ grayBitBltTable; bb.dst _ IndexBit[dest.sampleMap.base.word, [lc[dstBitIndex]]]; bb.dstBpl _ dest.sampleMap.bitsPerLine; bb.src.word _ @replicatedPixel; 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 _ function.srcFunc; bb.flags.dstFunc _ function.dstFunc; IF goodDest.sampleMap = NIL THEN BitBltOps.BitBltOp[bb] ELSE BitBltOps.BitBltOpCheck[bb, IndexBit[goodDest.sampleMap.base.word, [lc[dstBitIndex]]] ]; } 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 { bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; 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 _ IndexBit[dest.base.word, [lc[dstBitIndex]]]; bb.src.word _ source.base.word+yOffset; bb.src.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]; IF goodDest = NIL THEN BitBltOps.BitBltOp[bb] ELSE BitBltOps.BitBltOpCheck[bb, IndexBit[goodDest.base.word, [lc[dstBitIndex]]] ]; }; bb^ _ grayBitBltTable; bb.dstBpl _ dest.bitsPerLine; bb.srcDesc.gray.heightMinusOne _ source.sSize-1; bb.flags.srcFunc _ function.srcFunc; bb.flags.dstFunc _ function.dstFunc; 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; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bbTableSpace: PrincOps.BBTableSpace; 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.dst.bit _ bitsPerWord-bps; bb.dstBpl _ Shift[bitsPerWord, lgSkip]; bb.srcDesc _ [srcBpl[srcBitSkipDelta]]; bb.width _ bps; FOR i: NAT IN [0..Shift[1, lgSkip]) DO bb.src _ IndexBit[sampleMap.base.word, [lc[srcBitIndex]]]; bb.height _ Shift[size-i+skipMinusOne, -lgSkip]; bb.dst.word _ bufferPointer+i; BitBltOps.BitBltOp[bb]; srcBitIndex _ srcBitIndex + srcBitDelta; ENDLOOP; BitBltOps.BitBltOp[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; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bbTableSpace: PrincOps.BBTableSpace; 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 _ function.srcFunc; bb.flags.dstFunc _ function.dstFunc; bb.dstBpl _ dstBitSkipDelta; bb.src.bit _ bitsPerWord-bps; bb.srcDesc _ [srcBpl[Shift[bitsPerWord, lgSkip]]]; bb.width _ bps; FOR i: NAT IN [0..Shift[1, lgSkip]) DO bb.dst _ IndexBit[sampleMap.base.word, [lc[dstBitIndex]]]; bb.height _ Shift[size-i+skipMinusOne, -lgSkip]; bb.src.word _ bufferPointer+i; IF goodDest = NIL THEN BitBltOps.BitBltOp[bb] ELSE BitBltOps.BitBltOpCheck[bb, IndexBit[goodDest.base.word, [lc[dstBitIndex]]] ]; 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. LSlowSampleMapOpsImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Michael Plass, December 13, 1985 1:30:00 pm PST Willie-Sue, September 12, 1986 1:21:22 pm PDT IF x IN[0..max] THEN RETURN[x] ELSE ERROR RuntimeError.BoundsFault Round a bit size up to a whole number of words. make sure the words are not simply zeroes Try flushing the global function cache to get some space back. This record is to designed to avoid the need for partial-word access to the bit offset field, since the BITBLT format has carefully made this field word-aligned, and PrincOps.BitAddress has just as carefully made it hard to take advantage of this fact. Bug in Dorado BITBLT microcode (as of December 4, 1985) Number-theoretic: 0 <= remainder < d, n = quotient*d + remainder quotient _ qq.li; Number-theoretic: 0 <= remainder < d ΚΠ˜™Icodešœ Οmœ7™BK™/K™-K™—šΟk ˜ K˜ Kšœ;žœ˜>Kšœ ˜ Kšœ˜K˜—K˜šΠlnœž ˜#šž˜K˜ Kšœ1žœ˜4Kšœ ˜ —Kšžœ˜—šœž˜K˜Kšœ žœ˜&Kšœžœ˜#Kšœ žœ˜)Kšœ žœ˜&Kšžœžœžœ˜Kšœ žœ˜'Kšœ3˜3Kšœ žœ˜'Kšœžœ˜,Kšœ žœ˜)Kšœžœ˜/Kšœžœ˜#K˜Kšœžœ˜!Kšœžœžœ˜"K˜šœ žœ ˜K˜—š Πknœžœžœžœžœ˜0Kšœžœžœžœ ˜'K˜—š Οnœžœžœžœžœžœ˜8Kšœžœžœžœ ˜)K˜—š ‘œžœžœžœžœžœ˜2Kšžœžœžœ$˜8Kš žœžœ žœžœžœžœ™BK˜—š ‘ œžœžœžœžœžœ˜=Kšžœžœ ˜Kšœ˜K˜—š‘œžœ žœžœžœžœžœ˜LKšžœM˜SKšœ˜K˜—š ‘œžœžœžœžœ ˜+Kšœžœ˜šžœž˜Kšœ ˜ Kšœ˜Kšžœ˜—Kšœ˜K˜—š ‘œžœžœžœžœžœ˜/K™/šžœž˜Kšžœžœžœžœ˜MKš žœžœžœžœžœ˜F—Kšœ˜—K˜Kšœ žœ˜Kš œ žœžœžœ žœžœžœ˜9˜K˜—š ‘œžœžœ žœ žœ*žœ˜wKšœžœ7˜?—K˜š ‘œžœžœ žœ žœ*žœ˜xKšœžœ8˜@—K˜š ‘œžœžœ žœ žœ*žœ˜xKšœžœ7˜?—K˜Kšœ žœ˜&K˜š‘œžœ˜Kšœžœ žœ˜!Kšœ8žœ˜RK˜Kšœ žœ2˜BKšœžœžœ3˜Hšžœžœžœ˜%Kšœžœžœžœ ˜!Kšœ žœžœ˜1šœ˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ˜Kšœ"˜"Kšœ˜Kšœ ˜ Kšœ˜—Kšœ˜—šžœžœ˜Kšœ(˜(šœ˜Kšœ˜Kšœ7˜7Kšœ3˜3Kšœ˜Kšœ˜—Kšœ˜—Kšœ)™)šžœ˜ Kš œžœžœžœžœžœ˜1Kšœ žœ˜šžœž˜Kšœ˜Kšœ˜Kšœ˜Kšžœ˜—š žœžœžœžœ ž˜&šžœ žœ˜!Kšžœžœ žœžœ ˜<—Kšœžœ ˜Kšžœ˜K˜——Kšœ˜—K˜š ‘œžœ žœžœžœžœ˜OKšœ žœ˜Kšœ'žœžœ˜Dšžœžœžœ˜K™>Kšœ9˜9Kšœ=˜=Kšœ%˜%Kšœ`˜`Kšœ&˜&Kšœ˜—Kšœ˜K˜—š‘œžœžœžœ˜:Kšœ ˜ Kšœžœ"˜+Kšœžœ"˜+Kš œžœžœžœžœ˜=Kš œžœžœžœžœ˜=KšœU˜UKšœYžœ˜^Kšžœ˜ Kšœ˜—K˜š‘ œžœžœ*žœ˜JKšœ^˜^Kšœc˜cK˜—K˜š‘ œžœ žœ žœ#žœžœžœ˜rKšœ žœ2˜BKšžœ2˜8Kšœ˜K˜—šœ)˜)Kšœ žœ˜$Kšœ žœ ˜/Kšœ˜Kšœ˜K˜—šœ-˜-Kšœ žœ˜$Kšœ žœ ˜/Kšœ'žœžœ˜AKšœ˜K˜—šœ)˜)Kšœ žœ˜$Kšœ žœ ˜/Kšœ'žœžœžœ˜MKšœ˜K˜—š‘ œžœžœžœ žœ žœ7žœ%žœžœžœ!žœžœ˜υKšœžœžœ)˜GKšœ žœ˜,Kšœ žœžœ9˜QKšœžœžœ˜2Kšœžœžœžœ˜,Kš œžœžœžœžœžœ˜Všœ˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜—Kšžœ˜ Kšœ˜K˜—š‘ œžœžœžœžœžœžœ˜YKšœžœ0˜;Kšœžœ0˜;Kšœžœ˜-Kšœ žœžœf˜}KšœP˜PKš œ žœžœžœžœžœžœ˜@Kšœ žœ0˜AKšœžœ˜+šœ žœžœ˜(Kšžœ˜!Kšžœ@˜D—Kšžœžœ˜"Kšœ˜K˜—Kš ‘ œžœžœžœ žœ˜Kšœ,žœ˜5Kšœžœ0˜;Kšœžœ0˜;Kšœžœ˜-Kšœ žœžœf˜}K˜$KšœA˜Ašœ˜Kšœ3˜3Kšœ ˜ Kšœ4˜4Kšœ˜Kšœ ˜ Kšœ˜Kšœ&žœžœžœ7˜ƒK˜—šžœ žœžœ˜-KšžœL˜P—Kšœ˜K˜—Kš‘ œžœžœ%˜Yšœ˜KšœžœžœO˜_KšœžœžœO˜_šžœžœžœ ž˜šžœžœžœ ž˜KšœžœE˜UKšœL˜LKšžœ˜—Kšžœ˜—Kšœ˜K˜—š œžœžœž œžœ˜4Kšœό™όšžœžœž˜Kšœ(˜(Kšœžœžœ žœ˜0Kšž˜—K˜K˜—š‘œžœžœ žœžœ žœž œžœ˜~šœ˜KšœI˜IKšœžœ ˜$Kšœ˜—Kšžœ˜Kšœ˜K˜—Kš‘œžœžœžœ%˜\šœžœ˜!Kšœžœ˜Kšœ"˜"KšœžœžœO˜_KšœžœžœB˜Ršžœžœž˜šœ)˜)K˜$KšœA˜Ašœ žœžœ˜,KšœC˜CKšœ5˜5—šœ žœžœ˜+KšœD˜DKšœ7˜7—Kšœ˜Kšœ5˜5Kšœ˜Kšœ4˜4Kšœ'˜'Kšœ˜Kšœžœ˜Kšœ$˜$Kšœ$˜$šžœ žœžœ˜-KšžœO˜S—Kšœ˜—Kšžœ>˜E—Kšœ˜K˜—š‘œžœžœ#žœžœžœ-žœ˜Kšœžœ˜#Kšœžœ˜!Kšœžœ˜Kšœžœ˜K˜$KšœA˜Ašœ žœžœ˜1Kšœ1˜1Kšœ0˜0—šœ žœžœ˜1Kšœ3˜3Kšœ2˜2—Kšœ žœžœ1˜DKšœ žœžœ1˜DKšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœžœ ˜Kšœ$˜$Kšœ$˜$š žœžœ(žœ(žœ(žœ(žœ˜ΒKšœžœΟc˜4Kšžœžœžœ’˜Tš žœžœžœžœ’˜uKšœžœžœ$˜8KšœJ˜JKšœ"˜"Kšœ"˜"K˜—Kšœ˜—Kšœ:˜:Kšœ:˜:šžœ žœžœ˜-KšžœO˜S—Kšœ˜K˜—š‘œžœžœ+˜XKšœžœžœ1˜AKšœžœžœ1˜Ašžœžœžœ ž˜šžœžœžœ ž˜Kšœa˜aKšžœ˜—Kšžœ˜—Kšœ˜K˜—š œ žœžœžœΟf&œ˜PK˜—š‘œžœžœžœ+˜[Kšœžœ ˜(šžœ žœ žœžœ˜)šœ žœžœ˜6KšœX˜XKšœ@˜@—Kšœžœžœ1˜AKšœžœžœ1˜AK˜$KšœA˜AKšœžœžœ/˜Qšžœžœ˜'K™7Kšœžœžœ˜0Kšœ˜Kšœ˜—Kšœ˜Kšœ?˜?Kšœ'˜'Kšœ˜Kšœ žœ1˜@Kšœžœ1˜CKšœ$˜$Kšœ$˜$šžœžœžœ˜7KšžœY˜]—Kšœ˜—Kšžœ+˜/Kšœ˜K˜—š‘œžœžœžœžœžœ žœ.˜œKšœžœI˜TKšœB˜BKšœ˜K˜—Kš žœžœžœ žœ žœ˜6š ‘œžœžœžœžœžœ˜6Kšœ@™@šžœžœ˜ Kšœ ˜ Kšœ ˜ Kšžœ žœ!’!œ˜UKšœN˜NKšœ™Kšœžœ ˜#Kšœ˜—Kšžœžœ˜*Kšœ˜K˜—š ‘œžœžœžœžœ žœ˜7Kšœ$™$šžœžœ˜ Kšœ ˜ Kšžœ žœžœ˜9Kšžœžœžœ˜@Kšžœ)˜/Kšœ˜—Kšžœžœ˜Kšœ˜K˜—š ‘ œžœ žœžœžœžœ˜;Kšœžœ*˜5Kšžœ˜"Kšœ˜K˜—Kšœ žœ˜Kšœ žœ˜%š ‘ œžœžœžœ&žœ žœ.˜›Kšœžœ˜Kšœžœ˜Kšœžœ˜š‘œžœ˜/Kšœžœ;˜MKšœKžœ˜PKšœJ˜JKšœ˜—šžœžœ žœ"žœžœ žœ žœžœžœžœ˜ΦK˜$KšœA˜AKšœ žœ˜%š œ žœžœžœžœ˜Ašœ žœžœ˜,Kšœ-˜-Kšœ(˜(—Kš œ žœžœ žœžœ˜AKšœ5˜5Kšœ'˜'Kšœ žœ žœžœ˜0Kšœ"˜"Kšœ$˜$Kšœ9˜9šžœ žœžœ˜-KšžœO˜S—Kšœ˜—Kšœ˜Kšœ˜Kšœ0˜0Kšœ$˜$Kšœ$˜$Kšœ˜Kšž˜Kšœ˜—šžœžœžœ˜MKšžœ†˜ŠKšžœJ˜N—Kšœ˜K˜—š‘œžœžœžœžœžœžœ˜=Kšžœžœžœžœ˜7Kšžœžœžœžœ˜4Kšœ˜K˜—š ‘œžœžœ&žœ žœ.˜›Kšœžœ˜Kšœžœ˜Kšœžœ˜š œžœžœžœžœ˜=Kšœ žœ˜Kšœ žœ˜Kšœžœ žœ˜0Kšœžœ˜Kšœžœ˜-Kšœ žœ7˜Hšžœ ž˜Kšœžœ˜ Kšœ žœžœ˜+Kšœžœ˜Kšœžœ˜!šžœ ž˜šžœ žœž˜Kšœožœ-˜ŸKšžœcžœB˜¬—Kšœ˜Kšœ˜Kšžœ˜—Kšœ˜Kšœ˜Kšžœžœ žœ˜@Kšœ˜Kšžœ˜—Kšœ˜—Kšœ ˜ Kšœ˜K˜—š‘œžœžœžœ žœ)žœ žœ žœžœ˜“Jšœžœžœ˜,šžœ žœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜!Jšœžœ˜#JšœA˜AJ˜$Kšœžœžœ)˜Dšœ žœžœ˜1Kšœ4˜4Kšœ3˜3—Kšœ žœ7˜GKšœžœ˜#Kšœžœ˜Kšœžœ˜Kšžœžœ?˜MKšžœžœ?˜Mšžœžœžœžœžœžœžœž˜bKšœ&˜&Kšœ˜Kšžœ˜—Jšœ"˜"Jšœ;˜;Kšœ˜Kšœ˜Kšœ'˜'Kšœ'˜'Kšœ˜šžœžœžœž˜&Kšœ:˜:Kšœ0˜0Kšœ˜Jšœ˜Kšœ(˜(Kšžœ˜—Jšœ˜K˜—Kšœ˜K˜—š‘œžœžœžœ žœ)žœ žœ žœ@žœ˜ΛJšœžœžœ˜,šžœ žœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜!Jšœžœ˜#JšœA˜AJ˜$Kšœžœžœ)˜Dšœ žœžœ˜1Kšœ4˜4Kšœ3˜3—Kšœ žœ7˜GKšœžœ˜#Kšœžœ˜Kšœžœ˜Kšœ žœžœ˜*Kšžœžœ?˜MKšžœžœ?˜Mšžœžœžœžœžœžœžœž˜bKšœ&˜&Kšœ˜Kšžœ˜—Jšœ"˜"Kšœ˜Kšœ$˜$Kšœ$˜$Kšœ˜Kšœ˜Kšœ2˜2Kšœ˜šžœžœžœž˜&Kšœ:˜:Kšœ0˜0Kšœ˜šžœ žœžœ˜-JšžœO˜S—Kšœ(˜(Kšžœ˜—Kšœ˜—Kšœ˜K˜—š‘œžœžœžœ˜.Kšœžœ˜Kšœžœ ˜Kšœžœžœžœ5˜GKšœžœ˜šžœžœžœ ž˜Kšœžœ˜Kšœ˜Kšœ ˜ Kšžœ˜—Kšœ˜K˜—š‘œžœžœ žœžœžœžœžœžœžœ˜|Jšœ*˜*Kšžœžœžœ žœžœžœžœ˜[Kšœ˜—K˜—K˜Kšžœ˜K˜J˜—…—[x: