Squeak Class Documentation category index | class index  
 
BitBltSimulation
  category: VMConstruction-Interpreter
  superclass: InterpreterPlugin
  subclasses: BitBltSimulator

This class implements BitBlt, much as specified in the Blue Book spec.

Performance has been enhanced through the use of pointer variables such as sourceIndex and destIndex, and by separating several special cases of the inner loop.

Operation has been extended to color, with support for 1, 2, 4, 8, 16, and 32-bit pixel sizes. Conversion between different pixel sizes is facilitated by accepting an optional color map.

In addition to the original 16 combination rules, this BitBlt supports
16 fail (for old paint mode)
17 fail (for old mask mode)
18 sourceWord + destinationWord
19 sourceWord - destinationWord
20 rgbAdd: sourceWord with: destinationWord
21 rgbSub: sourceWord with: destinationWord
22 OLDrgbDiff: sourceWord with: destinationWord
23 OLDtallyIntoMap: destinationWord -- old vers doesn't clip to bit boundary
24 alphaBlend: sourceWord with: destinationWord
25 pixPaint: sourceWord with: destinationWord
26 pixMask: sourceWord with: destinationWord
27 rgbMax: sourceWord with: destinationWord
28 rgbMin: sourceWord with: destinationWord
29 rgbMin: sourceWord bitInvert32 with: destinationWord
30 alphaBlendConst: sourceWord with: destinationWord -- alpha passed as an arg
31 alphaPaintConst: sourceWord with: destinationWord -- alpha passed as an arg
32 rgbDiff: sourceWord with: destinationWord
33 tallyIntoMap: destinationWord
34 alphaBlendScaled: sourceWord with: destinationWord

This implementation has also been fitted with an experimental "warp drive" that allows abritrary scaling and rotation (and even limited affine deformations) with all BitBlt storage modes supported.

To add a new rule to BitBlt...
1. add the new rule method or methods in the category 'combination rules' of BBSim
2. describe it in the class comment of BBSim and in the class comment for BitBlt
3. add refs to initializeRuleTable in proper positions
4. add refs to initBBOpTable, following the pattern

instance methods
  accessing
  affectedBottom
affectedLeft
affectedRight
affectedTop

  color mapping
  mapPixel:flags:
rgbMap16To32:
rgbMap32To32:
rgbMapPixel:flags:

  combination rules
  OLDrgbDiff:with:
OLDtallyIntoMap:with:
addWord:with:
alphaBlend:with:
alphaBlendConst:with:
alphaBlendConst:with:paintMode:
alphaBlendScaled:with:
alphaPaintConst:with:
bitAnd:with:
bitAndInvert:with:
bitInvertAnd:with:
bitInvertAndInvert:with:
bitInvertDestination:with:
bitInvertOr:with:
bitInvertOrInvert:with:
bitInvertSource:with:
bitInvertXor:with:
bitOr:with:
bitOrInvert:with:
bitXor:with:
clearWord:with:
destinationWord:with:
merge:with:
partitionedAND:to:nBits:nPartitions:
partitionedAdd:to:nBits:nPartitions:
partitionedMax:with:nBits:nPartitions:
partitionedMin:with:nBits:nPartitions:
partitionedMul:with:nBits:nPartitions:
partitionedSub:from:nBits:nPartitions:
pickSourcePixels:flags:srcMask:destMask:srcShiftInc:dstShiftInc:
pixMask:with:
pixPaint:with:
pixSwap:with:
rgbAdd:with:
rgbDiff:with:
rgbMax:with:
rgbMin:with:
rgbMinInvert:with:
rgbMul:with:
rgbSub:with:
sourceWord:with:
subWord:with:
tallyIntoMap:with:

  initialize-release
  initBBOpTable
initialiseModule
moduleUnloaded:

  inner loop
  alphaSourceBlendBits16
alphaSourceBlendBits32
alphaSourceBlendBits8
copyLoop
copyLoopNoSource
copyLoopPixMap
warpLoop

  interpreter interface
  drawLoopX:Y:
fetchIntOrFloat:ofObject:
fetchIntOrFloat:ofObject:ifNil:
isIdentityMap:with:
loadBitBltDestForm
loadBitBltFrom:
loadBitBltFrom:warping:
loadBitBltSourceForm
loadColorMap
loadColorMapShiftOrMaskFrom:
loadHalftoneForm
loadWarpBltFrom:
setupColorMasks
setupColorMasksFrom:to:
showDisplayBits

  memory access
  dstLongAt:
dstLongAt:put:
dstLongAt:put:mask:
halftoneAt:
srcLongAt:
tableLookup:at:
tallyMapAt:
tallyMapAt:put:

  pixel mapping
  default8To32Table
deltaFrom:to:nSteps:
dither32To16:threshold:
pickWarpPixelAtX:y:
rgbMap:from:to:
warpLoopSetup
warpPickSmoothPixels:xDeltah:yDeltah:xDeltav:yDeltav:sourceMap:smoothing:dstShiftInc:
warpPickSourcePixels:xDeltah:yDeltah:xDeltav:yDeltav:dstShiftInc:flags:

  primitives
  primitiveCopyBits
primitiveDisplayString
primitiveDrawLoop
primitiveWarpBits

  setup
  checkSourceOverlap
clipRange
copyBits
copyBitsFrom:to:at:
copyBitsLockedAndClipped
destMaskAndPointerInit
ignoreSourceOrHalftone:
performCopyLoop
sourceSkewAndPointerInit
tryCopyingBitsQuickly
warpBits

  surface support
  loadSurfacePlugin
lockSurfaces
queryDestSurface:
querySourceSurface:
unlockSurfaces

  translation support
 

class methods
  initialization
  initialize
initializeRuleTable
test2
timingTest:

  system simulation
  copyBitsFrom:
simulatorClass
warpBitsFrom:

  translation
  declareCVarsIn:
moduleName
opTable

instance methods
  accessing top  
 

affectedBottom


 

affectedLeft


 

affectedRight


 

affectedTop


  color mapping top  
 

mapPixel:flags:

Color map the given source pixel.


 

rgbMap16To32:

Convert the given 16bit pixel value to a 32bit RGBA value.
Note: This method is intended to deal with different source formats.


 

rgbMap32To32:

Convert the given 32bit pixel value to a 32bit RGBA value.
Note: This method is intended to deal with different source formats.


 

rgbMapPixel:flags:

Perform the RGBA conversion for the given source pixel


  combination rules top  
 

OLDrgbDiff:with:

Subract the pixels in the source and destination, color by color,
and return the sum of the absolute value of all the differences.
For non-rgb, XOR the two and return the number of differing pixels.
Note that the region is not clipped to bit boundaries, but only to the
nearest (enclosing) word. This is because copyLoop does not do
pre-merge masking. For accurate results, you must subtract the
values obtained from the left and right fringes.


 

OLDtallyIntoMap:with:

Tally pixels into the color map. Note that the source should be
specified = destination, in order for the proper color map checks
to be performed at setup.
Note that the region is not clipped to bit boundaries, but only to the
nearest (enclosing) word. This is because copyLoop does not do
pre-merge masking. For accurate results, you must subtract the
values obtained from the left and right fringes.


 

addWord:with:


 

alphaBlend:with:

Blend sourceWord with destinationWord, assuming both are 32-bit pixels.
The source is assumed to have 255*alpha in the high 8 bits of each pixel,
while the high 8 bits of the destinationWord will be ignored.
The blend produced is alpha*source + (1-alpha)*dest, with
the computation being performed independently on each color
component. The high byte of the result will be 0.


 

alphaBlendConst:with:


 

alphaBlendConst:with:paintMode:

Blend sourceWord with destinationWord using a constant alpha.
Alpha is encoded as 0 meaning 0.0, and 255 meaning 1.0.
The blend produced is alpha*source + (1.0-alpha)*dest, with the
computation being performed independently on each color component.
This function could eventually blend into any depth destination,
using the same color averaging and mapping as warpBlt.
paintMode = true means do nothing if the source pixel value is zero.


 

alphaBlendScaled:with:

Blend sourceWord with destinationWord using the alpha value from sourceWord.
Alpha is encoded as 0 meaning 0.0, and 255 meaning 1.0.
In contrast to alphaBlend:with: the color produced is

srcColor + (1-srcAlpha) * dstColor

e.g., it is assumed that the source color is already scaled.


 

alphaPaintConst:with:


 

bitAnd:with:


 

bitAndInvert:with:


 

bitInvertAnd:with:


 

bitInvertAndInvert:with:


 

bitInvertDestination:with:


 

bitInvertOr:with:


 

bitInvertOrInvert:with:


 

bitInvertSource:with:


 

bitInvertXor:with:


 

bitOr:with:


 

bitOrInvert:with:


 

bitXor:with:


 

clearWord:with:


 

destinationWord:with:


 

merge:with:

Sender warpLoop is too big to include this in-line


 

partitionedAND:to:nBits:nPartitions:

AND word1 to word2 as nParts partitions of nBits each.
Any field of word1 not all-ones is treated as all-zeroes.
Used for erasing, eg, brush shapes prior to ORing in a color


 

partitionedAdd:to:nBits:nPartitions:

Add word1 to word2 as nParts partitions of nBits each.
This is useful for packed pixels, or packed colors


 

partitionedMax:with:nBits:nPartitions:

Max word1 to word2 as nParts partitions of nBits each


 

partitionedMin:with:nBits:nPartitions:

Min word1 to word2 as nParts partitions of nBits each


 

partitionedMul:with:nBits:nPartitions:

Multiply word1 with word2 as nParts partitions of nBits each.
This is useful for packed pixels, or packed colors.
Bug in loop version when non-white background


 

partitionedSub:from:nBits:nPartitions:

Subtract word1 from word2 as nParts partitions of nBits each.
This is useful for packed pixels, or packed colors


 

pickSourcePixels:flags:srcMask:destMask: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.


 

pixMask:with:


 

pixPaint:with:


 

pixSwap:with:

Swap the pixels in destWord


 

rgbAdd:with:


 

rgbDiff:with:

Subract the pixels in the source and destination, color by color,
and return the sum of the absolute value of all the differences.
For non-rgb, return the number of differing pixels.


 

rgbMax:with:


 

rgbMin:with:


 

rgbMinInvert:with:


 

rgbMul:with:


 

rgbSub:with:


 

sourceWord:with:


 

subWord:with:


 

tallyIntoMap:with:

Tally pixels into the color map. Those tallied are exactly those
in the destination rectangle. Note that the source should be
specified == destination, in order for the proper color map checks
to be performed at setup.


  initialize-release top  
 

initBBOpTable


 

initialiseModule


 

moduleUnloaded:

The module with the given name was just unloaded.
Make sure we have no dangling references.


  inner loop top  
 

alphaSourceBlendBits16

This version assumes
combinationRule = 34
sourcePixSize = 32
destPixSize = 16
sourceForm ~= destForm.


 

alphaSourceBlendBits32

This version assumes
combinationRule = 34
sourcePixSize = destPixSize = 32
sourceForm ~= destForm.
Note: The inner loop has been optimized for dealing
with the special cases of srcAlpha = 0.0 and srcAlpha = 1.0


 

alphaSourceBlendBits8

This version assumes
combinationRule = 34
sourcePixSize = 32
destPixSize = 8
sourceForm ~= destForm.
Note: This is not real blending since we don't have the source colors available.


 

copyLoop

This version of the inner loop assumes noSource = false.


 

copyLoopNoSource

Faster copyLoop when source not used. hDir and vDir are both
positive, and perload and skew are unused


 

copyLoopPixMap

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.


 

warpLoop

This version of the inner loop traverses an arbirary quadrilateral
source, thus producing a general affine transformation.


  interpreter interface top  
 

drawLoopX:Y:

This is the primitive implementation of the line-drawing loop.
See the comments in BitBlt>>drawLoopX:Y:


 

fetchIntOrFloat:ofObject:

Return the integer value of the given field of the given object. If the field contains a Float, truncate it and return its integral part. Fail if the given field does not contain a small integer or Float, or if the truncated Float is out of the range of small integers.


 

fetchIntOrFloat:ofObject:ifNil:

Return the integer value of the given field of the given object. If the field contains a Float, truncate it and return its integral part. Fail if the given field does not contain a small integer or Float, or if the truncated Float is out of the range of small integers.


 

isIdentityMap:with:

Return true if shiftTable/maskTable define an identity mapping.


 

loadBitBltDestForm

Load the dest form for BitBlt. Return false if anything is wrong, true otherwise.


 

loadBitBltFrom:

Load BitBlt from the oop.
This function is exported for the Balloon engine.


 

loadBitBltFrom:warping:

Load context from BitBlt instance. Return false if anything is amiss


 

loadBitBltSourceForm

Load the source form for BitBlt. Return false if anything is wrong, true otherwise.


 

loadColorMap

ColorMap, if not nil, must be longWords, and
2^N long, where N = sourceDepth for 1, 2, 4, 8 bits,
or N = 9, 12, or 15 (3, 4, 5 bits per color) for 16 or 32 bits.


 

loadColorMapShiftOrMaskFrom:


 

loadHalftoneForm

Load the halftone form


 

loadWarpBltFrom:


 

setupColorMasks

WARNING: For WarpBlt w/ smoothing the source depth is wrong here!


 

setupColorMasksFrom:to:

Setup color masks for converting an incoming RGB pixel value from srcBits to targetBits.


 

showDisplayBits


  memory access top  
 

dstLongAt:


 

dstLongAt:put:


 

dstLongAt:put:mask:

Store the given value back into destination form, using dstMask
to mask out the bits to be modified. This is an essiantial
read-modify-write operation on the destination form.


 

halftoneAt:

Return a value from the halftone pattern.


 

srcLongAt:


 

tableLookup:at:

Note: Nasty coercion only necessary for the non-inlined version of this method in C. Duh? Oh well, here's the full story. The code below will definitely be inlined so everything that calls this method is fine. But... the translator doesn't quite prune this method so it generates a C function that tries to attempt an array access on an int - and most compilers don't like this. If you don't know what I'm talking about try to remove the C coercion and you'll see what happens when you try to compile a new VM...


 

tallyMapAt:

Return the word at position idx from the colorMap


 

tallyMapAt:put:

Store the word at position idx in the colorMap


  pixel mapping top  
 

default8To32Table

Return the default translation table from 1..8 bit indexed colors to 32bit


 

deltaFrom:to:nSteps:

Utility routine for computing Warp increments.


 

dither32To16:threshold:

Dither the given 32bit word to 16 bit. Ignore alpha.


 

pickWarpPixelAtX:y:

Pick a single pixel from the source for WarpBlt.
Note: This method is crucial for WarpBlt speed w/o smoothing
and still relatively important when smoothing is used.


 

rgbMap:from:to:

Convert the given pixel value with nBitsIn bits for each color component to a pixel value with nBitsOut bits for each color component. Typical values for nBitsIn/nBitsOut are 3, 5, or 8.


 

warpLoopSetup

Setup values for faster pixel fetching.


 

warpPickSmoothPixels:xDeltah:yDeltah:xDeltav:yDeltav:sourceMap:smoothing:dstShiftInc:

Pick n (sub-) pixels from the source form, mapped by sourceMap,
average the RGB values, map by colorMap and return the new word.
This version is only called from WarpBlt with smoothingCount > 1


 

warpPickSourcePixels:xDeltah:yDeltah:xDeltav:yDeltav:dstShiftInc:flags:

Pick n pixels from the source form,
map by colorMap and return aligned by dstBitShift.
This version is only called from WarpBlt with smoothingCount = 1


  primitives top  
 

primitiveCopyBits

Invoke the copyBits primitive. If the destination is the display, then copy it to the screen.


 

primitiveDisplayString


 

primitiveDrawLoop

Invoke the line drawing primitive.


 

primitiveWarpBits

Invoke the warpBits primitive. If the destination is the display, then copy it to the screen.


  setup top  
 

checkSourceOverlap

check for possible overlap of source and destination


 

clipRange

clip and adjust source origin and extent appropriately


 

copyBits

This function is exported for the Balloon engine


 

copyBitsFrom:to:at:

Support for the balloon engine.


 

copyBitsLockedAndClipped

Perform the actual copyBits operation.
Assume: Surfaces have been locked and clipping was performed.


 

destMaskAndPointerInit

Compute masks for left and right destination words


 

ignoreSourceOrHalftone:


 

performCopyLoop

Based on the values provided during setup choose and
perform the appropriate inner loop function.


 

sourceSkewAndPointerInit

This is only used when source and dest are same depth,
ie, when the barrel-shift copy loop is used.


 

tryCopyingBitsQuickly

Shortcut for stuff that's being run from the balloon engine.
Since we do this at each scan line we should avoid the expensive
setup for source and destination.


 

warpBits


  surface support top  
 

loadSurfacePlugin

Load the surface support plugin


 

lockSurfaces

Get a pointer to the bits of any OS surfaces.


 

queryDestSurface:

Query the dimension of an OS surface.
This method is provided so that in case the inst vars of the
source form are broken, *actual* values of the OS surface
can be obtained. This might, for instance, happen if the user
resizes the main window.
Note: Moved to a separate function for better inlining of the caller.


 

querySourceSurface:

Query the dimension of an OS surface.
This method is provided so that in case the inst vars of the
source form are broken, *actual* values of the OS surface
can be obtained. This might, for instance, happen if the user
resizes the main window.
Note: Moved to a separate function for better inlining of the caller.


 

unlockSurfaces

Unlock the bits of any OS surfaces.


  translation support top  

class methods
  initialization top  
 

initialize

BitBltSimulation initialize


 

initializeRuleTable

BitBltSimulation initializeRuleTable


 

test2

BitBltSimulation test2


 

timingTest:

BitBltSimulation timingTest: 640@480


  system simulation top  
 

copyBitsFrom:

Simulate the copyBits primitive


 

simulatorClass

For running from Smalltalk - answer a class that can be used to
simulate the receiver. By default every plugin can simulate itself.


 

warpBitsFrom:

Simulate the warpBits primitive


  translation top  
 

declareCVarsIn:

Note: This method must be implemented by all subclasses to declare variables.


 

moduleName

Answer the receiver's module name that is used for the plugin's C code.


 

opTable