Author: Tim Felgentreff <[email protected]>
Branch: rbitblt
Changeset: r543:fb979403239a
Date: 2013-12-19 16:26 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/fb979403239a/
Log: finish copying squeakjs bitblt
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -649,7 +649,7 @@
if (combinationRule == 22 or combinationRule == 32):
s_frame.pop() # pops the next value under BitBlt
s_frame.push(s_bitblt.bitCount())
- else if w_dest_form.is_same_object(space.objtable['w_display']):
+ elif w_dest_form.is_same_object(space.objtable['w_display']):
w_bitmap = w_dest_form.fetch(space, 0)
assert isinstance(w_bitmap, model.W_DisplayBitmap)
w_bitmap.flush_to_screen()
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -1178,19 +1178,19 @@
def loadBitBlt(self):
self.success = True
- self.destForm = self.fetch(0)
- self.dest = self.loadForm(self.destForm)
- self.sourceForm = self.fetch(1)
- if self.sourceForm is not self.space.w_nil:
- self.source = self.loadForm(self.sourceForm)
+ self.w_destForm = self.fetch(0)
+ self.dest = self.loadForm(self.w_destForm)
+ self.w_sourceForm = self.fetch(1)
+ if self.w_sourceForm is not self.space.w_nil:
+ self.source = self.loadForm(self.w_sourceForm)
else:
self.source = None
self.halftone = self.loadHalftone(self.fetch(2))
self.combinationRule = self.space.unwrap_int(self.fetch(3))
self.destX = self.intOrIfNil(self.fetch(4), 0)
self.destY = self.intOrIfNil(self.fetch(5), 0)
- self.width = self.intOrIfNil(self.fetch(6), self.dest_form.width)
- self.height = self.intOrIfNil(self.fetch(7), self.dest_form.height)
+ self.width = self.intOrIfNil(self.fetch(6), self.dest.width)
+ self.height = self.intOrIfNil(self.fetch(7), self.dest.height)
self.clipX = self.intOrIfNil(self.fetch(10), 0)
self.clipY = self.intOrIfNil(self.fetch(11), 0)
self.clipW = self.intOrIfNil(self.fetch(12), self.width)
@@ -1206,19 +1206,72 @@
def copyBits(self):
self.bitCount = 0
self.clipRange()
- if (self.bbW <= 0 ir self.bbH <= 0):
+ if (self.bbW <= 0 or self.bbH <= 0):
return
self.destMaskAndPointerInit()
if not self.source:
self.copyLoopNoSource()
else:
self.checkSourceOverlap()
- if self.source.depth !== self.dest.depth:
+ if self.source.depth != self.dest.depth:
self.copyLoopPixMap()
else:
self.sourceSkewAndPointerInit()
self.copyLoop()
+ def checkSourceOverlap(self):
+ if (self.w_sourceForm is self.w_destForm and self.dy >= self.sy):
+ if (self.dy > self.sy):
+ self.vDir = -1
+ self.sy = (self.sy + self.bbH) - 1
+ self.dy = (self.dy + self.bbH) - 1
+ else:
+ if (self.dy == self.sy and self.dx > self.sx):
+ self.hDir = -1
+ self.sx = (self.sx + self.bbW) - 1 # start at right
+ self.dx = (self.dx + self.bbW) - 1
+ if (self.nWords > 1):
+ t = self.mask1 # and fix up masks
+ self.mask1 = self.mask2
+ self.mask2 = t
+ self.destIndex = (self.dy * self.dest.pitch) + (self.dx /
self.dest.pixPerWord | 0) # recompute since dx, dy change
+ self.destDelta = (self.dest.pitch * self.vDir) - (self.nWords *
self.hDir)
+
+ def sourceSkewAndPointerInit(self):
+ pixPerM1 = self.dest.pixPerWord - 1 # Pix per word is power of two, so
self makes a mask
+ sxLowBits = self.sx & pixPerM1
+ dxLowBits = self.dx & pixPerM1
+ # check if need to preload buffer
+ # (i.e., two words of source needed for first word of destination)
+ dWid = -1
+ if (self.hDir > 0):
+ if self.bbW < (self.dest.pixPerWord - dxLowBits):
+ dWid = self.bbW
+ else:
+ dWid = self.dest.pixPerWord - dxLowBits
+ self.preload = (sxLowBits + dWid) > pixPerM1
+ else:
+ if self.bbW < (dxLowBits + 1):
+ dWid = self.bbW
+ else:
+ dWid = dxLowBits + 1
+ self.preload = ((sxLowBits - dWid) + 1) < 0
+
+ if self.source.msb:
+ self.skew = (sxLowBits - dxLowBits) * self.dest.depth
+ else:
+ self.skew = (dxLowBits - sxLowBits) * self.dest.depth
+ if (self.preload):
+ if (self.skew < 0):
+ self.skew += 32
+ else:
+ self.skew -= 32
+ # calculate increments from end of one line to start of next
+ self.sourceIndex = (self.sy * self.source.pitch) + (self.sx / (32 /
self.source.depth) |0)
+ self.sourceDelta = (self.source.pitch * self.vDir) - (self.nWords *
self.hDir)
+ if (self.preload):
+ self.sourceDelta -= self.hDir
+
def clipRange(self):
# intersect with destForm bounds
if self.clipX < 0:
@@ -1231,174 +1284,399 @@
self.clipW = self.dest.width - self.clipX
if self.clipY + self.clipH > self.dest.height:
self.clipH = self.dest.height - self.clipY
-
# intersect with clipRect
- leftOffset = max(self.clipY - self.destY, 0)
+ leftOffset = max(self.clipX - self.destX, 0)
self.sx = self.sourceX + leftOffset
self.dx = self.destX + leftOffset
self.bbW = self.width - leftOffset
- rightOffset =
+ rightOffset = (self.dx + self.bbW) - (self.clipX + self.clipW)
+ if rightOffset > 0:
+ self.bbW -= rightOffset
+ topOffset = max(self.clipY - self.destY, 0)
+ self.sy = self.sourceY + topOffset
+ self.dy = self.destY + topOffset
+ self.bbH = self.height - topOffset
+ bottomOffset = (self.dy + self.bbH) - (self.clipY + self.clipH)
+ if bottomOffset > 0:
+ self.bbH -= bottomOffset
+ # intersect with sourceForm bounds
+ if not self.source:
+ return
+ if self.sx < 0:
+ self.dx -= self.sx
+ self.bbW += self.sx
+ self.sx = 0
+ if (self.sx + self.bbW) > self.source.width:
+ self.bbW -= (self.sx + self.bbW) - self.source.width
+ if self.sy < 0:
+ self.dy -= self.sy
+ self.bbH += self.sy
+ self.sy = 0
+ if (self.sy + self.bbH) > self.source.height:
+ self.bbH -= (self.sy + self.bbH) - self.source.height
+ def rshift(self, val, n):
+ return rarithmetic.intmask(val >> n if val >= 0 else (val +
0x100000000) >> n)
- def compute_masks(self):
- self.dest_bits = self.dest_form.w_bits
- self.dest_raster = (self.dest_form.width - 1) // BitBltShadow.WordSize
+ 1
- if self.source_form is not None:
- self.source_bits = self.source_form.w_bits
- self.source_raster = (self.source_form.width - 1) //
BitBltShadow.WordSize + 1
+ def destMaskAndPointerInit(self):
+ pixPerM1 = self.dest.pixPerWord - 1 # pixPerWord is power-of-two, so
this makes a mask
+ startBits = self.dest.pixPerWord - (self.dx & pixPerM1) # how many px
in 1st word
+ endBits = (((self.dx + self.bbW) - 1) & pixPerM1) + 1
+ if self.dest.msb:
+ self.mask1 = self.rshift(0xFFFFFFFF, (32 - (startBits *
self.dest.depth)))
+ self.mask2 = 0xFFFFFFFF << (32 - (endBits * self.dest.depth))
else:
- self.source_bits = None
- self.source_raster = 0
- # Halftone form is set during synchronization
- self.skew = (self.sx - self.dx) & (BitBltShadow.WordSize - 1)
- start_bits = BitBltShadow.WordSize - (self.dx & (BitBltShadow.WordSize
- 1))
- self.mask1 = BitBltShadow.RightMasks[start_bits]
- end_bits = (BitBltShadow.WordSize - 1) - ((self.dx + self.w - 1) &
(BitBltShadow.WordSize - 1))
- self.mask2 = ~BitBltShadow.RightMasks[end_bits]
- if self.skew == 0:
- self.skew_mask = rarithmetic.r_uint(0)
+ self.mask1 = 0xFFFFFFFF << (32 - (startBits * self.dest.depth))
+ self.mask2 = self.rshift(0xFFFFFFFF, (32 - (endBits *
self.dest.depth)))
+ if self.bbW < startBits:
+ self.mask1 = self.mask1 & self.mask2
+ self.mask2 = 0
+ self.nWords = 1
else:
- self.skew_mask = BitBltShadow.RightMasks[BitBltShadow.WordSize -
self.skew]
- if self.w < start_bits:
- self.mask1 = self.mask1 & self.mask2
- self.mask2 = rarithmetic.r_uint(0)
- self.n_words = 1
+ self.nWords = (((self.bbW - startBits) + pixPerM1) /
self.dest.pixPerWord | 0) + 1
+ self.hDir = 1
+ self.vDir = 1
+ self.destIndex = (self.dy * self.dest.pitch) + (self.dx /
self.dest.pixPerWord | 0)
+ self.destDelta = (self.dest.pitch * self.vDir) - (self.nWords *
self.hDir)
+
+ def copyLoopNoSource(self):
+ halftoneWord = 0xFFFFFFFF
+ for i in range(self.bbH):
+ if self.halftone:
+ halftoneWord = self.halftone[(self.dy + i) %
len(self.halftone)]
+ # first word in row is masked
+ destMask = self.mask1
+ destWord = self.dest.w_bits.getword(self.destIndex)
+ mergeWord = self.mergeFn(halftoneWord, destWord)
+ destWord = (destMask & mergeWord) | (destWord & (~destMask))
+ self.dest.w_bits.setword(self.destIndex, destWord)
+ self.destIndex += 1
+ destMask = 0xFFFFFFFF
+ # the central horizontal loop requires no store masking
+ if self.combinationRule == 3: # store rule requires no dest merging
+ for word in range(2, self.nWords):
+ self.dest.w_bits.setword(self.destIndex, halftoneWord)
+ self.destIndex += 1
+ else:
+ for word in range(2, self.nWords):
+ destWord = self.dest.w_bits.getword(self.destIndex)
+ mergeWord = self.mergeFn(halftoneWord, destWord)
+ self.dest.w_bits.setword(self.destIndex, mergeWord)
+ self.destIndex += 1
+ # last word in row is masked
+ if self.nWords > 1:
+ destMask = self.mask2
+ destWord = self.dest.w_bits.getword(self.destIndex)
+ mergeWord = self.mergeFn(halftoneWord, destWord)
+ destWord = (destMask & mergeWord) | (destWord & (~destMask))
+ self.dest.w_bits.setword(self.destIndex, destWord)
+ self.destIndex += 1
+ self.destIndex += self.destDelta
+
+ def copyLoopPixMap(self):
+ # This version of the inner loop maps source pixels
+ # to a destination form with different depth. Because it is already
+ # unweildy, the loop is not unrolled as in the other versions.
+ # Preload, skew and skewMask are all overlooked, since pickSourcePixels
+ # delivers its destination word already properly aligned.
+ # Note that pickSourcePixels could be copied in-line at the top of
+ # the horizontal loop, and some of its inits moved out of the loop.
+ #
+ # The loop has been rewritten to use only one pickSourcePixels call.
+ # The idea is that the call itself could be inlined. If we decide not
+ # to inline pickSourcePixels we could optimize the loop instead.
+ sourcePixMask = BitBltShadow.MaskTable[this.source.depth]
+ destPixMask = BitBltShadow.MaskTable[this.dest.depth]
+ self.sourceIndex = (self.sy * self.source.pitch) + (self.sx /
self.source.pixPerWord | 0)
+ scrStartBits = self.source.pixPerWord - (self.sx &
(self.source.pixPerWord - 1))
+ if self.bbW < scrStartBits:
+ nSourceIncs = 0
else:
- self.n_words = (self.w - start_bits - 1) // BitBltShadow.WordSize
+ 2
+ nSourceIncs = ((self.bbW - scrStartBits) / self.source.pixPerWord
| 0) + 1
+ # Note following two items were already calculated in destmask setup!
+ self.sourceDelta = self.source.pitch - nSourceIncs
+ startBits = self.dest.pixPerWord - (self.dx & (self.dest.pixPerWord -
1))
+ endBits = (((self.dx + self.bbW) - 1) & (self.dest.pixPerWord - 1)) + 1
+ if self.bbW < startBits:
+ startBits = self.bbW # ?!
+ srcShift = (self.sx & (self.source.pixPerWord - 1)) * self.source.depth
+ dstShift = (self.dx & (self.dest.pixPerWord - 1)) * self.dest.depth
+ srcShiftInc = self.source.depth
+ dstShiftInc = self.dest.depth
+ dstShiftLeft = 0
+ if (self.source.msb):
+ srcShift = (32 - self.source.depth) - srcShift
+ srcShiftInc = -srcShiftInc
- def check_overlap(self):
- self.h_dir = 1
- self.v_dir = 1
- if (self.source_form is not None and
- self.source_form.w_self().is_same_object(self.dest_form.w_self())
and
- self.dy >= self.sy):
- if self.dy > self.sy:
- self.v_dir = -1
- self.sy = self.sy + self.h - 1
- self.dy = self.dy + self.h - 1
- elif self.dx > self.sx:
- self.h_dir = -1
- self.sx = self.sx + self.w - 1
- self.dx = self.dx + self.w - 1
- self.skew_mask = ~self.skew_mask
- self.mask1, self.mask2 = self.mask2, self.mask1
+ if (self.dest.msb):
+ dstShift = (32 - self.dest.depth) - dstShift
+ dstShiftInc = -dstShiftInc
+ dstShiftLeft = 32 - self.dest.depth
- def calculate_offsets(self):
- self.preload = (self.source_form is not None and (
- self.skew != 0 and
- self.skew <= (self.sx & (BitBltShadow.WordSize - 1))))
- if self.h_dir < 0:
- self.preload = not self.preload
- self.source_index = self.sy * self.source_raster + (self.sx //
BitBltShadow.WordSize)
- self.dest_index = self.dy * self.dest_raster + (self.dx //
BitBltShadow.WordSize)
- self.source_delta = (self.source_raster *
- self.v_dir -
- ((self.n_words + (1 if self.preload else 0)) *
- self.h_dir))
- self.dest_delta = self.dest_raster * self.v_dir - self.n_words *
self.h_dir
+ for i in range(self.bbH):
+ if self.halftone:
+ halftoneWord = self.halftone[(self.dy + i) %
self.halftone.length]
+ else:
+ halftoneWord = 0xFFFFFFFF
+ self.srcBitShift = srcShift
+ self.dstBitShift = dstShift
+ self.destMask = self.mask1
+ nPix = startBits
+ words = self.nWords
+ # Here is the horizontal loop...
+ for word in range(words + 1):
+ skewWord = self.pickSourcePixels(nPix, sourcePixMask,
destPixMask, srcShiftInc, dstShiftInc)
+ # align next word to leftmost pixel
+ self.dstBitShift = dstShiftLeft
+ if self.destMask == 0xFFFFFFFF: # avoid read-modify-write
+ self.dest.w_bits.setword(
+ self.destIndex,
+ self.mergeFn(skewWord & halftoneWord,
self.dest.w_bits.getword(self.destIndex))
+ )
+ else: # General version using dest masking
+ destWord = self.dest.w_bits.getword(self.destIndex)
+ mergeWord = self.mergeFn(skewWord & halftoneWord, destWord
& self.destMask)
+ destWord = (self.destMask & mergeWord) | (destWord &
(~self.destMask))
+ self.dest.w_bits.setword(self.destIndex, destWord)
- def copy_loop(self):
- space = self.space
- no_skew_mask = ~self.skew_mask
- for i in xrange(1, self.h + 1):
- if self.halftone_bits:
- halftone_word = self.halftone_bits[self.dy %
len(self.halftone_bits)]
- self.dy = self.dy + self.v_dir
+ self.destIndex += 1
+ if (words == 2): # is the next word the last word?
+ self.destMask = self.mask2
+ nPix = endBits
+ else: # use fullword mask for inner loop
+ self.destMask = 0xFFFFFFFF
+ nPix = self.dest.pixPerWord
+ self.sourceIndex += self.sourceDelta
+ self.destIndex += self.destDelta
+
+ def pickSourcePixels(self, nPixels, srcMask, dstMask, srcShiftInc,
dstShiftInc):
+ # Pick nPix pixels starting at srcBitIndex from the source, map by the
+ # color map, and justify them according to dstBitIndex in the
resulting destWord.
+ sourceWord = self.source.w_bits.getword(self.sourceIndex)
+ destWord = 0
+ srcShift = self.srcBitShift # put into temp for speed
+ dstShift = self.dstBitShift
+ nPix = nPixels
+ # always > 0 so we can use do { } while(--nPix);
+ if (self.cmLookupTable): # a little optimization for (pretty crucial)
blits using indexed lookups only
+ for px in range(nPix + 1):
+ sourcePix = self.rshift(sourceWord, srcShift) & srcMask
+ destPix = self.cmLookupTable[sourcePix & self.cmMask]
+ # adjust dest pix index
+ destWord = destWord | ((destPix & dstMask) << dstShift)
+ # adjust source pix index
+ dstShift += dstShiftInc
+ srcShift += srcShiftInc
+ if srcShift & 0xFFFFFFE0:
+ if (self.source.msb):
+ srcShift += 32
+ else:
+ srcShift -= 32
+ self.sourceIndex += 1
+ sourceWord = self.source.w_bits.getword(self.sourceIndex)
+ else:
+ raise PrimitiveFailedError()
+ self.srcBitShift = srcShift # Store back
+ return destWord
+
+ def rotate32bit(self, thisWord, prevWord, skewMask, notSkewMask, unskew):
+ if unskew < 0:
+ rotated = self.rshift(prevWord & notSkewMask, -unskew)
+ else:
+ rotated = (prevWord & notSkewMask) << unskew
+ if self.skew < 0:
+ rotated = rotated | self.rshift(thisWord & skewMask, -self.skew)
+ else:
+ rotated = rotated | (thisWord & skewMask) << self.skew
+ return rotated
+
+ def copyLoop(self):
+ # self version of the inner loop assumes we do have a source
+ sourceLimit = self.source.w_bits.size()
+ hInc = self.hDir
+ # init skew (the difference in word alignment of source and dest)
+ unskew = 0
+ skewMask = 0
+ if (self.skew == -32):
+ self.skew = unskew = skewMask = 0
+ else:
+ if (self.skew < 0):
+ unskew = self.skew + 32
+ skewMask = 0xFFFFFFFF << -self.skew
else:
- halftone_word = BitBltShadow.AllOnes
- skew_word = halftone_word
- if self.preload:
- prev_word = self.source_bits.getword(self.source_index)
- self.source_index = self.source_index + self.h_dir
+ if (self.skew == 0):
+ unskew = 0
+ skewMask = 0xFFFFFFFF
+ else:
+ unskew = self.skew - 32
+ skewMask = self.rshift(0xFFFFFFFF, self.skew)
+ notSkewMask = ~skewMask
+
+ # init halftones
+ halftoneWord = 0
+ halftoneHeight = 0
+ if (self.halftone):
+ halftoneWord = self.halftone[0]
+ halftoneHeight = len(self.halftone)
+ else:
+ halftoneWord = 0xFFFFFFFF
+ halftoneHeight = 0
+
+ # now loop over all lines
+ y = self.dy
+ for i in range(1, self.bbH + 1):
+ if (halftoneHeight > 1):
+ halftoneWord = self.halftone[y % halftoneHeight]
+ y += self.vDir
+
+ if (self.preload):
+ prevWord = self.source.w_bits.getword(self.sourceIndex)
+ self.sourceIndex += hInc
else:
- prev_word = 0
- merge_mask = self.mask1
- for word in xrange(1, self.n_words + 1):
- if self.source_form is not None:
- prev_word = prev_word & self.skew_mask
- if (self.source_index < 0
- or self.source_index >= self.source_bits.size()):
- this_word = self.source_bits.getword(0)
+ prevWord = 0
+
+ destMask = self.mask1
+ # pick up next word
+ thisWord = self.source.w_bits.getword(self.sourceIndex)
+ self.sourceIndex += hInc
+ skewWord = self.rotate32bit(thisWord, prevWord, skewMask,
notSkewMask, unskew)
+ prevWord = thisWord
+ destWord = self.dest.w_bits.getword(self.destIndex)
+ mergeWord = self.mergeFn(skewWord & halftoneWord, destWord)
+ destWord = (destMask & mergeWord) | (destWord & (~destMask))
+ self.dest.w_bits.setword(self.destIndex, destWord)
+ # The central horizontal loop requires no store masking
+ self.destIndex += hInc
+ destMask = 0xFFFFFFFF
+ if (self.combinationRule == 3): # Store mode avoids dest merge
function
+ if ((self.skew == 0) and (halftoneWord == 0xFFFFFFFF)):
+ # Non-skewed with no halftone
+ if (self.hDir == -1):
+ for word in range(2, self.nWords):
+ thisWord =
self.source.w_bits.getword(self.sourceIndex)
+ self.dest.w_bits.setword(self.destIndex, thisWord)
+ self.sourceIndex += hInc
+ self.destIndex += hInc
else:
- this_word = self.source_bits.getword(self.source_index)
- skew_word = prev_word | (this_word & no_skew_mask)
- prev_word = this_word
- skew_word = (self.bit_shift(skew_word, self.skew) |
- self.bit_shift(skew_word, self.skew -
BitBltShadow.WordSize))
- merge_word = rarithmetic.r_uint(self.merge(
- skew_word & halftone_word,
- self.dest_bits.getword(self.dest_index)
- ))
- __new = (
- (merge_mask & merge_word) |
- (~merge_mask & self.dest_bits.getword(self.dest_index))
- )
- self.dest_bits.setword(self.dest_index, __new)
- self.source_index = self.source_index + self.h_dir
- self.dest_index = self.dest_index + self.h_dir
- if word == (self.n_words - 1):
- merge_mask = self.mask2
+ for word in range(2, self.nWords):
+ self.dest.w_bits.setword(self.destIndex, prevWord)
+ prevWord =
self.source.w_bits.getword(self.sourceIndex)
+ self.destIndex += hInc
+ self.sourceIndex += hInc
else:
- merge_mask = BitBltShadow.AllOnes
- self.source_index = self.source_index + self.source_delta
- self.dest_index = self.dest_index + self.dest_delta
+ # skewed and/or halftoned
+ for word in range(2, self.nWords):
+ thisWord = self.source.w_bits.getword(self.sourceIndex)
+ self.sourceIndex += hInc
+ skewWord = self.rotate32bit(thisWord, prevWord,
skewMask, notSkewMask, unskew)
+ prevWord = thisWord
+ self.dest.w_bits.setword(self.destIndex, skewWord &
halftoneWord)
+ self.destIndex += hInc
+ else: # Dest merging here...
+ for word in range(2, self.nWords):
+ thisWord = self.source.w_bits.getword(self.sourceIndex) #
pick up next word
+ self.sourceIndex += hInc
+ skewWord = self.rotate32bit(thisWord, prevWord, skewMask,
notSkewMask, unskew)
+ prevWord = thisWord
+ mergeWord = self.mergeFn(skewWord & halftoneWord,
self.dest.w_bits.getword(self.destIndex))
+ self.dest.w_bits.setword(self.destIndex, mergeWord)
+ self.destIndex += hInc
+ # last word with masking and all
+ if (self.nWords > 1):
+ destMask = self.mask2
+ if (self.sourceIndex >= 0 and self.sourceIndex < sourceLimit):
+ # NOTE: we are currently overrunning source bits in some
cases
+ # self test makes up for it.
+ thisWord = self.source.w_bits.getword(self.sourceIndex) #
pick up next word
+ self.sourceIndex += hInc
+ skewWord = self.rotate32bit(thisWord, prevWord, skewMask,
notSkewMask, unskew)
+ destWord = self.dest.w_bits.getword(self.destIndex)
+ mergeWord = self.mergeFn(skewWord & halftoneWord, destWord)
+ destWord = (destMask & mergeWord) | (destWord & (~destMask))
+ self.dest.w_bits.setword(self.destIndex, destWord)
+ self.destIndex += hInc
+ self.sourceIndex += self.sourceDelta
+ self.destIndex += self.destDelta
- def bit_shift(self, target, amount):
- if amount > 31 or amount < -31:
- return 0
- elif amount > 0:
- return (rarithmetic.r_uint(target) << amount) &
BitBltShadow.AllOnes
- elif amount == 0:
- return target
- else:
- return (rarithmetic.r_uint(target) >> -amount)
+ def mergeFn(self, src, dest):
+ return rarithmetic.r_uint(self.merge(
+ rarithmetic.r_uint(src),
+ rarithmetic.r_uint(dest)
+ ))
def merge(self, source_word, dest_word):
assert isinstance(source_word, rarithmetic.r_uint) and
isinstance(dest_word, rarithmetic.r_uint)
- if self.combination_rule == 0:
+ if self.combinationRule == 0:
return 0
- elif self.combination_rule == 1:
+ elif self.combinationRule == 1:
return source_word & dest_word
- elif self.combination_rule == 2:
+ elif self.combinationRule == 2:
return source_word & ~dest_word
- elif self.combination_rule == 3:
+ elif self.combinationRule == 3:
return source_word
- elif self.combination_rule == 4:
+ elif self.combinationRule == 4:
return ~source_word & dest_word
- elif self.combination_rule == 5:
+ elif self.combinationRule == 5:
return dest_word
- elif self.combination_rule == 6:
+ elif self.combinationRule == 6:
return source_word ^ dest_word
- elif self.combination_rule == 7:
+ elif self.combinationRule == 7:
return source_word | dest_word
- elif self.combination_rule == 8:
+ elif self.combinationRule == 8:
return ~source_word & ~dest_word
- elif self.combination_rule == 9:
+ elif self.combinationRule == 9:
return ~source_word ^ dest_word
- elif self.combination_rule == 10:
+ elif self.combinationRule == 10:
return ~dest_word
- elif self.combination_rule == 11:
+ elif self.combinationRule == 11:
return source_word | ~dest_word
- elif self.combination_rule == 12:
+ elif self.combinationRule == 12:
return ~source_word
- elif self.combination_rule == 13:
+ elif self.combinationRule == 13:
return ~source_word | dest_word
- elif self.combination_rule == 14:
+ elif self.combinationRule == 14:
return ~source_word | ~dest_word
- elif self.combination_rule == 15:
- return dest_word & BitBltShadow.AllOnes
- elif self.combination_rule >= 16 and self.combination_rule <= 24:
+ elif self.combinationRule >= 15 and self.combinationRule <= 17:
return dest_word
- elif self.combination_rule == 25:
+ elif self.combinationRule == 18:
+ return source_word + dest_word
+ elif self.combinationRule == 19:
+ return source_word - dest_word
+ elif self.combinationRule >= 20 and self.combinationRule <= 24:
+ return source_word
+ elif self.combinationRule == 25:
if source_word == 0:
return dest_word
else:
- return source_word | (dest_word & ~source_word)
- elif 26 <= self.combination_rule <= 41:
+ return self.partitionedANDtonBitsnPartitions(
+ ~source_word,
+ dest_word,
+ self.dest.depth,
+ self.dest.pixPerWord
+ )
+ elif self.combinationRule == 26:
+ return self.partitionedANDtonBitsnPartitions(
+ ~source_word,
+ dest_word,
+ self.dest.depth,
+ self.dest.pixPerWord
+ )
+ elif 26 < self.combinationRule <= 41:
return dest_word
else:
raise error.PrimitiveFailedError()
+ def partitionedANDtonBitsnPartitions(self, word1, word2, nBits, nParts):
+ # partition mask starts at the right
+ mask = BitBltShadow.MaskTable[nBits]
+ result = 0
+ for i in range(1, nParts + 1):
+ if ((word1 & mask) == mask):
+ result = result | (word2 & mask)
+ # slide left to next partition
+ mask = mask << nBits
+ return result
+
def as_string(bb):
return 'aBitBlt (destX: %d, destY: %d, sx: %d, sy: %d, dx: %d, dy: %d,
w: %d, h: %d, hDir: %d, vDir: %d, sDelta: %d, dDelta: %d, skew: %d, sI: %d, dI:
%d)' % (
bb.dest_x, bb.dest_y, bb.sx, bb.sy, bb.dx, bb.dy, bb.w, bb.h,
bb.h_dir, bb.v_dir, bb.source_delta, bb.dest_delta, bb.skew, bb.source_index,
bb.dest_index)
@@ -1424,11 +1702,22 @@
self.width = self.space.unwrap_int(self.fetch(1))
self.height = self.space.unwrap_int(self.fetch(2))
self.depth = self.space.unwrap_int(self.fetch(3))
+ if self.width < 0 or self.height < 0:
+ raise PrimitiveFailedError()
+ self.msb = self.depth > 0
+ if self.depth < 0:
+ self.depth = -self.depth
+ if self.depth == 0:
+ raise PrimitiveFailedError()
w_offset = self.fetch(4)
assert isinstance(w_offset, model.W_PointersObject)
if not w_offset is self.space.w_nil:
- self.offset_x = self.space.unwrap_int(w_offset._fetch(0))
- self.offset_y = self.space.unwrap_int(w_offset._fetch(1))
+ self.offsetX = self.space.unwrap_int(w_offset._fetch(0))
+ self.offsetY = self.space.unwrap_int(w_offset._fetch(1))
+ self.pixPerWord = 32 / self.depth
+ self.pitch = (self.width + (self.pixPerWord - 1)) / self.pixPerWord | 0
+ if self.w_bits.size() != (self.pitch * self.height):
+ raise PrimitiveFailedError()
# def replace_bits(self):
# w_bits = self.w_bits
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit