VM Maker: VMMaker.oscog-nice.2909.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

VM Maker: VMMaker.oscog-nice.2909.mcz

commits-2
 
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-nice.2909.mcz

==================== Summary ====================

Name: VMMaker.oscog-nice.2909
Author: nice
Time: 23 December 2020, 9:54:51.201058 pm
UUID: 6869c4f1-9d80-40c3-8409-7c05e087edf5
Ancestors: VMMaker.oscog-eem.2908

WIP: implement new BitBlt ops (rules) for alpha compositing

                "42" alphaScale:with:
                "43" alphaUnscale:with:
                "44" alphaBlendUnscaled:with:
               
This is a proposal implementation for https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/505

The generated C code compiles, but it's otherwise mostly yet unused and untested code. I commit it before I loose it.
There's probably more to do for letting accelerated code work (PI).

=============== Diff against VMMaker.oscog-eem.2908 ===============

Item was changed:
  SmartSyntaxInterpreterPlugin subclass: #BitBltSimulation
  instanceVariableNames: 'destForm sourceForm halftoneForm combinationRule destX destY width height sourceX sourceY clipX clipY clipWidth clipHeight sourceWidth sourceHeight sourceDepth sourcePitch sourceBits sourcePPW sourceMSB destWidth destHeight destDepth destPitch destBits destPPW destMSB bitCount skew mask1 mask2 preload nWords destMask hDir vDir sourceIndex sourceDelta destIndex destDelta sx sy dx dy bbW bbH halftoneHeight noSource noHalftone halftoneBase sourceAlpha srcBitShift dstBitShift bitBltOop affectedL affectedR affectedT affectedB opTable maskTable ditherMatrix4x4 ditherThresholds16 ditherValues16 hasSurfaceLock warpSrcShift warpSrcMask warpAlignShift warpAlignMask warpBitShiftTable querySurfaceFn lockSurfaceFn unlockSurfaceFn isWarping cmFlags cmMask cmShiftTable cmMaskTable cmLookupTable cmBitsPerColor dither8Lookup componentAlphaModeColor componentAlphaModeAlpha ungammaLookupTable gammaLookupTable numGCsOnInvocation bitBltIsReceiver endOfDestination endOfSource'
  classVariableNames: 'AllOnes AlphaIndex BBClipHeightIndex BBClipWidthIndex BBClipXIndex BBClipYIndex BBColorMapIndex BBDestFormIndex BBDestXIndex BBDestYIndex BBHalftoneFormIndex BBHeightIndex BBLastIndex BBRuleIndex BBSourceFormIndex BBSourceXIndex BBSourceYIndex BBWarpBase BBWidthIndex BBXTableIndex BEBitBltIndex BinaryPoint BlueIndex ColorMapFixedPart ColorMapIndexedPart ColorMapNewStyle ColorMapPresent CrossedX EndOfRun FixedPt1 FormBitsIndex FormDepthIndex FormHeightIndex FormWidthIndex GreenIndex OpTable OpTableSize RedIndex'
  poolDictionaries: ''
  category: 'VMMaker-Interpreter'!
 
+ !BitBltSimulation commentStamp: 'nice 10/31/2020 23:39' prior: 0!
- !BitBltSimulation commentStamp: 'tpr 3/25/2013 16:50' prior: 0!
  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
  35 alphaBlendScaled: sourceWord with: "unused here - only used by FXBlt"
  36 alphaBlendScaled: sourceWord with: "unused here - only used by FXBlt"
  37 rgbMul: sourceWord with: destinationWord
  38 pixSwap: sourceWord with: destinationWord
  39 pixClear: sourceWord with: destinationWord
  40 fixAlpha: sourceWord with: destinationWord
  41 rgbComponentAlpha: sourceWord with: destinationWord
+ 42 alphaScale: ignoredSourceWord with: destinationWord
+ 43 alphaUnscale: ignoredSourceWord with: destinationWord
+ 44 alphaBlendUnscaled: 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
  !

Item was changed:
  ----- Method: BitBltSimulation class>>initializeRuleTable (in category 'initialization') -----
  initializeRuleTable
  "BitBltSimulation initializeRuleTable"
  "**WARNING** You MUST change initBBOpTable if you change this"
  OpTable := #(
  "0" clearWord:with:
  "1" bitAnd:with:
  "2" bitAndInvert:with:
  "3" sourceWord:with:
  "4" bitInvertAnd:with:
  "5" destinationWord:with:
  "6" bitXor:with:
  "7" bitOr:with:
  "8" bitInvertAndInvert:with:
  "9" bitInvertXor:with:
  "10" bitInvertDestination:with:
  "11" bitOrInvert:with:
  "12" bitInvertSource:with:
  "13" bitInvertOr:with:
  "14" bitInvertOrInvert:with:
  "15" destinationWord:with:
  "16" destinationWord:with: "unused - was old paint"
  "17" destinationWord:with: "unused - was old mask"
  "18" addWord:with:
  "19" subWord:with:
  "20" rgbAdd:with:
  "21" rgbSub:with:
  "22" OLDrgbDiff:with:
  "23" OLDtallyIntoMap:with:
  "24" alphaBlend:with:
  "25" pixPaint:with:
  "26" pixMask:with:
  "27" rgbMax:with:
  "28" rgbMin:with:
  "29" rgbMinInvert:with:
  "30" alphaBlendConst:with:
  "31" alphaPaintConst:with:
  "32" rgbDiff:with:
  "33" tallyIntoMap:with:
  "34" alphaBlendScaled:with:
 
  "35" alphaBlendScaled:with: "unused here - only used by FXBlt"
  "36" alphaBlendScaled:with: "unused here - only used by FXBlt"
  "37" rgbMul:with:
  "38" pixSwap:with:
  "39" pixClear:with:
  "40" fixAlpha:with:
  "41" rgbComponentAlpha:with:
+ "42" alphaScale:with:
+ "43" alphaUnscale:with:
+ "44" alphaBlendUnscaled:with:
  ).
  OpTableSize := OpTable size + 1.  "0-origin indexing"
  !

Item was added:
+ ----- Method: BitBltSimulation>>alphaBlendUnscaled:with: (in category 'combination rules') -----
+ alphaBlendUnscaled: sourceWord with: destinationWord
+ "Blend sourceWord with destinationWord using the alpha value from both sourceWord and destinationWord.
+ Alpha is encoded as 0 meaning 0.0, and 255 meaning 1.0.
+ The alpha channel and color produced are
+
+ srcAlpha + (destAlpha*(1-srcAlpha))
+ (srcAlpha*srcColor + (destAlpha*(1-srcAlpha)*dstColor)) / (srcAlpha + (destAlpha*(1-srcAlpha)))
+
+ In contrast to alphaBlend:with: the method does not assume that destination form is opaque.
+ In contrast to alphaBlendScaled:with: the method does not assume that colors have been pre-scaled (muliplied) by alpha channel."
+ | alpha blendA result blendRB blendG |
+ <inline: false>
+ <returnTypeC: 'unsigned int'>
+ <var: #sourceWord type: 'unsigned int'>
+ <var: #destinationWord type: 'unsigned int'>
+ <var: #blendRB type: 'unsigned int'>
+ <var: #blendG type: 'unsigned int'>
+ <var: #result type: 'unsigned int'>
+ <var: #alpha type: 'unsigned int'>
+ <var: #blendA type: 'unsigned int'>
+ alpha := sourceWord >> 24.  "High 8 bits of source pixel, assuming ARGB encoding"
+ alpha = 0 ifTrue: [ ^ destinationWord ].
+ alpha = 255 ifTrue: [ ^ sourceWord ].
+
+ blendA := 16rFF * alpha + (16rFF - alpha * (destinationWord >> 24)) + 16rFF. "blend alpha channels"
+ blendA := blendA + (blendA - 1 >> 8 bitAnd: 16rFF) >> 8 bitAnd: 16rFF. "divide by 255"
+
+ blendRB := ((sourceWord bitAnd: 16rFF00FF) * alpha) +
+ ((destinationWord bitAnd: 16rFF00FF) * (blendA-alpha))
+ / blendA. "blend red and blue"
+
+ blendG := ((sourceWord bitAnd: 16r00FF00) * alpha) +
+ ((destinationWord bitAnd: 16r00FF00) * (blendA-alpha))
+ / blendA. "blend green"
+ result := (blendRB bitOr: blendG) bitOr: blendA << 24.
+ ^ result
+ !

Item was added:
+ ----- Method: BitBltSimulation>>alphaScale:with: (in category 'combination rules') -----
+ alphaScale: sourceWord with: destinationWord
+ "Scale (premultiply) the destination with its alpha channel.
+ Note that sourceWord is ignored."
+ | alpha rb g |
+ <inline: false> "Do NOT inline this into optimized loops"
+ <returnTypeC: 'unsigned int'>
+ <var: #sourceWord type: 'unsigned int'>
+ <var: #destinationWord type: 'unsigned int'>
+ <var: #rb type: 'unsigned int'>
+ <var: #g type: 'unsigned int'>
+ <var: #alpha type: 'unsigned int'>
+ alpha := destinationWord >> 24.  "High 8 bits is opacity (ARGB format)"
+ rb := ((destinationWord bitAnd: 16rFF00FF) * alpha >> 8 bitAnd: 16rFF00FF). "scale red and blue components"
+ g := ((destinationWord bitAnd: 16r00FF00) * alpha >> 8 bitAnd: 16r00FF00). "scale green component"
+ ^(g bitOr: rb) bitOr: (destinationWord bitAnd: 16rFF000000) "recompose"!

Item was added:
+ ----- Method: BitBltSimulation>>alphaUnscale:with: (in category 'combination rules') -----
+ alphaUnscale: sourceWord with: destinationWord
+ "Unscale (divide) the destination with its alpha channel.
+ Note that sourceWord is ignored."
+ | alpha rb g rgb carry |
+ <inline: false> "Do NOT inline this into optimized loops"
+ <returnTypeC: 'unsigned int'>
+ <var: #sourceWord type: 'unsigned int'>
+ <var: #destinationWord type: 'unsigned int'>
+ <var: #rb type: 'unsigned int'>
+ <var: #g type: 'unsigned int'>
+ <var: #rgb type: 'unsigned int'>
+ <var: #alpha type: 'unsigned int'>
+ <var: #carry type: 'unsigned int'>
+ alpha := destinationWord >> 24.  "High 8 bits is opacity (ARGB format)"
+ alpha = 0 ifTrue: [^0].
+ rb := (destinationWord bitAnd: 16rFF00FF) << 8 / alpha. "unscale red and blue components"
+ g := (destinationWord bitAnd: 16r00FF00) / alpha. "unscale green component"
+ carry := ((rb >> 8 bitAnd: 16rAA00AA) >> 1 bitOr: (rb >> 8 bitAnd: 16r550055) << 1)
+ bitOr: ((g bitAnd: 16r00AA00) >> 1 bitOr: (g bitAnd: 16r005500) << 1).
+ carry := (carry bitAnd: 16rCCCCCC) >> 2 bitOr: (carry bitAnd: 16r333333) << 2.
+ carry := (carry bitAnd: 16rF0F0F0) >> 4 bitOr: (carry bitAnd: 16r0F0F0F) << 4.
+ rgb := (rb bitAnd: 16rFF00FF) bitOr: (g << 8 bitAnd: 16r00FF00).
+ rgb := rgb bitOr: carry.  "saturate RGB components if division overflows"
+ ^rgb bitOr: (destinationWord bitAnd: 16rFF000000) "restore alpha"!

Item was changed:
  ----- Method: BitBltSimulation>>initBBOpTable (in category 'initialize-release') -----
  initBBOpTable
  self cCode: 'opTable[0+1] = (void *)clearWordwith'.
  self cCode: 'opTable[1+1] = (void *)bitAndwith'.
  self cCode: 'opTable[2+1] = (void *)bitAndInvertwith'.
  self cCode: 'opTable[3+1] = (void *)sourceWordwith'.
  self cCode: 'opTable[4+1] = (void *)bitInvertAndwith'.
  self cCode: 'opTable[5+1] = (void *)destinationWordwith'.
  self cCode: 'opTable[6+1] = (void *)bitXorwith'.
  self cCode: 'opTable[7+1] = (void *)bitOrwith'.
  self cCode: 'opTable[8+1] = (void *)bitInvertAndInvertwith'.
  self cCode: 'opTable[9+1] = (void *)bitInvertXorwith'.
  self cCode: 'opTable[10+1] = (void *)bitInvertDestinationwith'.
  self cCode: 'opTable[11+1] = (void *)bitOrInvertwith'.
  self cCode: 'opTable[12+1] = (void *)bitInvertSourcewith'.
  self cCode: 'opTable[13+1] = (void *)bitInvertOrwith'.
  self cCode: 'opTable[14+1] = (void *)bitInvertOrInvertwith'.
  self cCode: 'opTable[15+1] = (void *)destinationWordwith'.
  self cCode: 'opTable[16+1] = (void *)destinationWordwith'.
  self cCode: 'opTable[17+1] = (void *)destinationWordwith'.
  self cCode: 'opTable[18+1] = (void *)addWordwith'.
  self cCode: 'opTable[19+1] = (void *)subWordwith'.
  self cCode: 'opTable[20+1] = (void *)rgbAddwith'.
  self cCode: 'opTable[21+1] = (void *)rgbSubwith'.
  self cCode: 'opTable[22+1] = (void *)OLDrgbDiffwith'.
  self cCode: 'opTable[23+1] = (void *)OLDtallyIntoMapwith'.
  self cCode: 'opTable[24+1] = (void *)alphaBlendwith'.
  self cCode: 'opTable[25+1] = (void *)pixPaintwith'.
  self cCode: 'opTable[26+1] = (void *)pixMaskwith'.
  self cCode: 'opTable[27+1] = (void *)rgbMaxwith'.
  self cCode: 'opTable[28+1] = (void *)rgbMinwith'.
  self cCode: 'opTable[29+1] = (void *)rgbMinInvertwith'.
  self cCode: 'opTable[30+1] = (void *)alphaBlendConstwith'.
  self cCode: 'opTable[31+1] = (void *)alphaPaintConstwith'.
  self cCode: 'opTable[32+1] = (void *)rgbDiffwith'.
  self cCode: 'opTable[33+1] = (void *)tallyIntoMapwith'.
  self cCode: 'opTable[34+1] = (void *)alphaBlendScaledwith'.
  self cCode: 'opTable[35+1] = (void *)alphaBlendScaledwith'.
  self cCode: 'opTable[36+1] = (void *)alphaBlendScaledwith'.
  self cCode: 'opTable[37+1] = (void *)rgbMulwith'.
  self cCode: 'opTable[38+1] = (void *)pixSwapwith'.
  self cCode: 'opTable[39+1] = (void *)pixClearwith'.
  self cCode: 'opTable[40+1] = (void *)fixAlphawith'.
+ self cCode: 'opTable[41+1] = (void *)rgbComponentAlphawith'.
+ self cCode: 'opTable[42+1] = (void *)alphaScalewith'.
+ self cCode: 'opTable[43+1] = (void *)alphaUnscalewith'.
+ self cCode: 'opTable[44+1] = (void *)alphaBlendUnscaledwith'.!
- self cCode: 'opTable[41+1] = (void *)rgbComponentAlphawith'.!

Reply | Threaded
Open this post in threaded view
|

Re: VM Maker: VMMaker.oscog-nice.2909.mcz

Karl Ramberg
 
Finally :-D

Best,
Karl


On Wed, Dec 23, 2020 at 9:55 PM <[hidden email]> wrote:
 
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-nice.2909.mcz

==================== Summary ====================

Name: VMMaker.oscog-nice.2909
Author: nice
Time: 23 December 2020, 9:54:51.201058 pm
UUID: 6869c4f1-9d80-40c3-8409-7c05e087edf5
Ancestors: VMMaker.oscog-eem.2908

WIP: implement new BitBlt ops (rules) for alpha compositing

                "42" alphaScale:with:
                "43" alphaUnscale:with:
                "44" alphaBlendUnscaled:with:

This is a proposal implementation for https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/505

The generated C code compiles, but it's otherwise mostly yet unused and untested code. I commit it before I loose it.
There's probably more to do for letting accelerated code work (PI).

=============== Diff against VMMaker.oscog-eem.2908 ===============

Item was changed:
  SmartSyntaxInterpreterPlugin subclass: #BitBltSimulation
        instanceVariableNames: 'destForm sourceForm halftoneForm combinationRule destX destY width height sourceX sourceY clipX clipY clipWidth clipHeight sourceWidth sourceHeight sourceDepth sourcePitch sourceBits sourcePPW sourceMSB destWidth destHeight destDepth destPitch destBits destPPW destMSB bitCount skew mask1 mask2 preload nWords destMask hDir vDir sourceIndex sourceDelta destIndex destDelta sx sy dx dy bbW bbH halftoneHeight noSource noHalftone halftoneBase sourceAlpha srcBitShift dstBitShift bitBltOop affectedL affectedR affectedT affectedB opTable maskTable ditherMatrix4x4 ditherThresholds16 ditherValues16 hasSurfaceLock warpSrcShift warpSrcMask warpAlignShift warpAlignMask warpBitShiftTable querySurfaceFn lockSurfaceFn unlockSurfaceFn isWarping cmFlags cmMask cmShiftTable cmMaskTable cmLookupTable cmBitsPerColor dither8Lookup componentAlphaModeColor componentAlphaModeAlpha ungammaLookupTable gammaLookupTable numGCsOnInvocation bitBltIsReceiver endOfDestination endOfSource'
        classVariableNames: 'AllOnes AlphaIndex BBClipHeightIndex BBClipWidthIndex BBClipXIndex BBClipYIndex BBColorMapIndex BBDestFormIndex BBDestXIndex BBDestYIndex BBHalftoneFormIndex BBHeightIndex BBLastIndex BBRuleIndex BBSourceFormIndex BBSourceXIndex BBSourceYIndex BBWarpBase BBWidthIndex BBXTableIndex BEBitBltIndex BinaryPoint BlueIndex ColorMapFixedPart ColorMapIndexedPart ColorMapNewStyle ColorMapPresent CrossedX EndOfRun FixedPt1 FormBitsIndex FormDepthIndex FormHeightIndex FormWidthIndex GreenIndex OpTable OpTableSize RedIndex'
        poolDictionaries: ''
        category: 'VMMaker-Interpreter'!

+ !BitBltSimulation commentStamp: 'nice 10/31/2020 23:39' prior: 0!
- !BitBltSimulation commentStamp: 'tpr 3/25/2013 16:50' prior: 0!
  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
        35 alphaBlendScaled: sourceWord with:   "unused here - only used by FXBlt"
        36 alphaBlendScaled: sourceWord with:   "unused here - only used by FXBlt"
        37 rgbMul: sourceWord with: destinationWord
        38 pixSwap: sourceWord with: destinationWord
        39 pixClear: sourceWord with: destinationWord
        40 fixAlpha: sourceWord with: destinationWord
        41 rgbComponentAlpha: sourceWord with: destinationWord
+       42 alphaScale: ignoredSourceWord with: destinationWord
+       43 alphaUnscale: ignoredSourceWord with: destinationWord
+       44      alphaBlendUnscaled: 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
  !

Item was changed:
  ----- Method: BitBltSimulation class>>initializeRuleTable (in category 'initialization') -----
  initializeRuleTable
        "BitBltSimulation initializeRuleTable"
        "**WARNING** You MUST change initBBOpTable if you change this"
        OpTable := #(
                "0" clearWord:with:
                "1" bitAnd:with:
                "2" bitAndInvert:with:
                "3" sourceWord:with:
                "4" bitInvertAnd:with:
                "5" destinationWord:with:
                "6" bitXor:with:
                "7" bitOr:with:
                "8" bitInvertAndInvert:with:
                "9" bitInvertXor:with:
                "10" bitInvertDestination:with:
                "11" bitOrInvert:with:
                "12" bitInvertSource:with:
                "13" bitInvertOr:with:
                "14" bitInvertOrInvert:with:
                "15" destinationWord:with:
                "16" destinationWord:with: "unused - was old paint"
                "17" destinationWord:with: "unused - was old mask"
                "18" addWord:with:
                "19" subWord:with:
                "20" rgbAdd:with:
                "21" rgbSub:with:
                "22" OLDrgbDiff:with:
                "23" OLDtallyIntoMap:with:
                "24" alphaBlend:with:
                "25" pixPaint:with:
                "26" pixMask:with:
                "27" rgbMax:with:
                "28" rgbMin:with:
                "29" rgbMinInvert:with:
                "30" alphaBlendConst:with:
                "31" alphaPaintConst:with:
                "32" rgbDiff:with:
                "33" tallyIntoMap:with:
                "34" alphaBlendScaled:with:

                "35" alphaBlendScaled:with:     "unused here - only used by FXBlt"
                "36" alphaBlendScaled:with:     "unused here - only used by FXBlt"
                "37" rgbMul:with:
                "38" pixSwap:with:
                "39" pixClear:with:
                "40" fixAlpha:with:
                "41" rgbComponentAlpha:with:
+               "42" alphaScale:with:
+               "43" alphaUnscale:with:
+               "44" alphaBlendUnscaled:with:
        ).
        OpTableSize := OpTable size + 1.  "0-origin indexing"
  !

Item was added:
+ ----- Method: BitBltSimulation>>alphaBlendUnscaled:with: (in category 'combination rules') -----
+ alphaBlendUnscaled: sourceWord with: destinationWord
+       "Blend sourceWord with destinationWord using the alpha value from both sourceWord and destinationWord.
+       Alpha is encoded as 0 meaning 0.0, and 255 meaning 1.0.
+       The alpha channel and color produced are
+
+               srcAlpha + (destAlpha*(1-srcAlpha))
+               (srcAlpha*srcColor + (destAlpha*(1-srcAlpha)*dstColor)) / (srcAlpha + (destAlpha*(1-srcAlpha)))
+
+       In contrast to alphaBlend:with: the method does not assume that destination form is opaque.
+       In contrast to alphaBlendScaled:with: the method does not assume that colors have been pre-scaled (muliplied) by alpha channel."
+       | alpha blendA result blendRB blendG |
+       <inline: false>
+       <returnTypeC: 'unsigned int'>
+       <var: #sourceWord type: 'unsigned int'>
+       <var: #destinationWord type: 'unsigned int'>
+       <var: #blendRB type: 'unsigned int'>
+       <var: #blendG type: 'unsigned int'>
+       <var: #result type: 'unsigned int'>
+       <var: #alpha type: 'unsigned int'>
+       <var: #blendA type: 'unsigned int'>
+       alpha := sourceWord >> 24.  "High 8 bits of source pixel, assuming ARGB encoding"
+       alpha = 0 ifTrue: [ ^ destinationWord ].
+       alpha = 255 ifTrue: [ ^ sourceWord ].
+       
+       blendA := 16rFF * alpha + (16rFF - alpha * (destinationWord >> 24)) + 16rFF. "blend alpha channels"
+       blendA := blendA + (blendA - 1 >> 8 bitAnd: 16rFF) >> 8 bitAnd: 16rFF. "divide by 255"
+
+       blendRB := ((sourceWord bitAnd: 16rFF00FF) * alpha) +
+                               ((destinationWord bitAnd: 16rFF00FF) * (blendA-alpha))
+                               / blendA.       "blend red and blue"
+
+       blendG := ((sourceWord bitAnd: 16r00FF00) * alpha) +
+                               ((destinationWord bitAnd: 16r00FF00) * (blendA-alpha))
+                               / blendA.       "blend green"
+       result := (blendRB bitOr: blendG) bitOr: blendA << 24.
+       ^ result
+ !

Item was added:
+ ----- Method: BitBltSimulation>>alphaScale:with: (in category 'combination rules') -----
+ alphaScale: sourceWord with: destinationWord
+       "Scale (premultiply) the destination with its alpha channel.
+       Note that sourceWord is ignored."
+       | alpha rb g |
+       <inline: false> "Do NOT inline this into optimized loops"
+       <returnTypeC: 'unsigned int'>
+       <var: #sourceWord type: 'unsigned int'>
+       <var: #destinationWord type: 'unsigned int'>
+       <var: #rb type: 'unsigned int'>
+       <var: #g type: 'unsigned int'>
+       <var: #alpha type: 'unsigned int'>
+       alpha := destinationWord >> 24.  "High 8 bits is opacity (ARGB format)"
+       rb := ((destinationWord bitAnd: 16rFF00FF) * alpha >> 8 bitAnd: 16rFF00FF). "scale red and blue components"
+       g := ((destinationWord bitAnd: 16r00FF00) * alpha >> 8 bitAnd: 16r00FF00). "scale green component"
+       ^(g bitOr: rb) bitOr: (destinationWord bitAnd: 16rFF000000) "recompose"!

Item was added:
+ ----- Method: BitBltSimulation>>alphaUnscale:with: (in category 'combination rules') -----
+ alphaUnscale: sourceWord with: destinationWord
+       "Unscale (divide) the destination with its alpha channel.
+       Note that sourceWord is ignored."
+       | alpha rb g rgb carry |
+       <inline: false> "Do NOT inline this into optimized loops"
+       <returnTypeC: 'unsigned int'>
+       <var: #sourceWord type: 'unsigned int'>
+       <var: #destinationWord type: 'unsigned int'>
+       <var: #rb type: 'unsigned int'>
+       <var: #g type: 'unsigned int'>
+       <var: #rgb type: 'unsigned int'>
+       <var: #alpha type: 'unsigned int'>
+       <var: #carry type: 'unsigned int'>
+       alpha := destinationWord >> 24.  "High 8 bits is opacity (ARGB format)"
+       alpha = 0 ifTrue: [^0].
+       rb := (destinationWord bitAnd: 16rFF00FF) << 8 / alpha. "unscale red and blue components"
+       g := (destinationWord bitAnd: 16r00FF00) / alpha. "unscale green component"
+       carry := ((rb >> 8 bitAnd: 16rAA00AA) >> 1 bitOr: (rb >> 8 bitAnd: 16r550055) << 1)
+               bitOr: ((g bitAnd: 16r00AA00) >> 1 bitOr: (g bitAnd: 16r005500) << 1).
+       carry := (carry bitAnd: 16rCCCCCC) >> 2 bitOr: (carry bitAnd: 16r333333) << 2.
+       carry := (carry bitAnd: 16rF0F0F0) >> 4 bitOr: (carry bitAnd: 16r0F0F0F) << 4.
+       rgb := (rb bitAnd: 16rFF00FF) bitOr: (g << 8 bitAnd: 16r00FF00).
+       rgb := rgb bitOr: carry.  "saturate RGB components if division overflows"
+       ^rgb bitOr: (destinationWord bitAnd: 16rFF000000) "restore alpha"!

Item was changed:
  ----- Method: BitBltSimulation>>initBBOpTable (in category 'initialize-release') -----
  initBBOpTable
        self cCode: 'opTable[0+1] = (void *)clearWordwith'.
        self cCode: 'opTable[1+1] = (void *)bitAndwith'.
        self cCode: 'opTable[2+1] = (void *)bitAndInvertwith'.
        self cCode: 'opTable[3+1] = (void *)sourceWordwith'.
        self cCode: 'opTable[4+1] = (void *)bitInvertAndwith'.
        self cCode: 'opTable[5+1] = (void *)destinationWordwith'.
        self cCode: 'opTable[6+1] = (void *)bitXorwith'.
        self cCode: 'opTable[7+1] = (void *)bitOrwith'.
        self cCode: 'opTable[8+1] = (void *)bitInvertAndInvertwith'.
        self cCode: 'opTable[9+1] = (void *)bitInvertXorwith'.
        self cCode: 'opTable[10+1] = (void *)bitInvertDestinationwith'.
        self cCode: 'opTable[11+1] = (void *)bitOrInvertwith'.
        self cCode: 'opTable[12+1] = (void *)bitInvertSourcewith'.
        self cCode: 'opTable[13+1] = (void *)bitInvertOrwith'.
        self cCode: 'opTable[14+1] = (void *)bitInvertOrInvertwith'.
        self cCode: 'opTable[15+1] = (void *)destinationWordwith'.
        self cCode: 'opTable[16+1] = (void *)destinationWordwith'.
        self cCode: 'opTable[17+1] = (void *)destinationWordwith'.
        self cCode: 'opTable[18+1] = (void *)addWordwith'.
        self cCode: 'opTable[19+1] = (void *)subWordwith'.
        self cCode: 'opTable[20+1] = (void *)rgbAddwith'.
        self cCode: 'opTable[21+1] = (void *)rgbSubwith'.
        self cCode: 'opTable[22+1] = (void *)OLDrgbDiffwith'.
        self cCode: 'opTable[23+1] = (void *)OLDtallyIntoMapwith'.
        self cCode: 'opTable[24+1] = (void *)alphaBlendwith'.
        self cCode: 'opTable[25+1] = (void *)pixPaintwith'.
        self cCode: 'opTable[26+1] = (void *)pixMaskwith'.
        self cCode: 'opTable[27+1] = (void *)rgbMaxwith'.
        self cCode: 'opTable[28+1] = (void *)rgbMinwith'.
        self cCode: 'opTable[29+1] = (void *)rgbMinInvertwith'.
        self cCode: 'opTable[30+1] = (void *)alphaBlendConstwith'.
        self cCode: 'opTable[31+1] = (void *)alphaPaintConstwith'.
        self cCode: 'opTable[32+1] = (void *)rgbDiffwith'.
        self cCode: 'opTable[33+1] = (void *)tallyIntoMapwith'.
        self cCode: 'opTable[34+1] = (void *)alphaBlendScaledwith'.
        self cCode: 'opTable[35+1] = (void *)alphaBlendScaledwith'.
        self cCode: 'opTable[36+1] = (void *)alphaBlendScaledwith'.     
        self cCode: 'opTable[37+1] = (void *)rgbMulwith'.
        self cCode: 'opTable[38+1] = (void *)pixSwapwith'.
        self cCode: 'opTable[39+1] = (void *)pixClearwith'.
        self cCode: 'opTable[40+1] = (void *)fixAlphawith'.
+       self cCode: 'opTable[41+1] = (void *)rgbComponentAlphawith'.
+       self cCode: 'opTable[42+1] = (void *)alphaScalewith'.
+       self cCode: 'opTable[43+1] = (void *)alphaUnscalewith'.
+       self cCode: 'opTable[44+1] = (void *)alphaBlendUnscaledwith'.!
-       self cCode: 'opTable[41+1] = (void *)rgbComponentAlphawith'.!

Reply | Threaded
Open this post in threaded view
|

Re: VM Maker: VMMaker.oscog-nice.2909.mcz

David T. Lewis
 
Bravo! Thank you Nicolas.

Dave

On Sun, Dec 27, 2020 at 09:42:47PM +0100, karl ramberg wrote:

>  
> Finally :-D
>
> Best,
> Karl
>
>
> On Wed, Dec 23, 2020 at 9:55 PM <[hidden email]> wrote:
>
> >
> > Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:
> > http://source.squeak.org/VMMaker/VMMaker.oscog-nice.2909.mcz
> >
> > ==================== Summary ====================
> >
> > Name: VMMaker.oscog-nice.2909
> > Author: nice
> > Time: 23 December 2020, 9:54:51.201058 pm
> > UUID: 6869c4f1-9d80-40c3-8409-7c05e087edf5
> > Ancestors: VMMaker.oscog-eem.2908
> >
> > WIP: implement new BitBlt ops (rules) for alpha compositing
> >
> >                 "42" alphaScale:with:
> >                 "43" alphaUnscale:with:
> >                 "44" alphaBlendUnscaled:with:
> >
> > This is a proposal implementation for
> > https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/505
> >
> > The generated C code compiles, but it's otherwise mostly yet unused and
> > untested code. I commit it before I loose it.
> > There's probably more to do for letting accelerated code work (PI).
> >
> > =============== Diff against VMMaker.oscog-eem.2908 ===============
> >
> > Item was changed:
> >   SmartSyntaxInterpreterPlugin subclass: #BitBltSimulation
> >         instanceVariableNames: 'destForm sourceForm halftoneForm
> > combinationRule destX destY width height sourceX sourceY clipX clipY
> > clipWidth clipHeight sourceWidth sourceHeight sourceDepth sourcePitch
> > sourceBits sourcePPW sourceMSB destWidth destHeight destDepth destPitch
> > destBits destPPW destMSB bitCount skew mask1 mask2 preload nWords destMask
> > hDir vDir sourceIndex sourceDelta destIndex destDelta sx sy dx dy bbW bbH
> > halftoneHeight noSource noHalftone halftoneBase sourceAlpha srcBitShift
> > dstBitShift bitBltOop affectedL affectedR affectedT affectedB opTable
> > maskTable ditherMatrix4x4 ditherThresholds16 ditherValues16 hasSurfaceLock
> > warpSrcShift warpSrcMask warpAlignShift warpAlignMask warpBitShiftTable
> > querySurfaceFn lockSurfaceFn unlockSurfaceFn isWarping cmFlags cmMask
> > cmShiftTable cmMaskTable cmLookupTable cmBitsPerColor dither8Lookup
> > componentAlphaModeColor componentAlphaModeAlpha ungammaLookupTable
> > gammaLookupTable numGCsOnInvocation bitBltIsReceiver endOfDestination
> > endOfSource'
> >         classVariableNames: 'AllOnes AlphaIndex BBClipHeightIndex
> > BBClipWidthIndex BBClipXIndex BBClipYIndex BBColorMapIndex BBDestFormIndex
> > BBDestXIndex BBDestYIndex BBHalftoneFormIndex BBHeightIndex BBLastIndex
> > BBRuleIndex BBSourceFormIndex BBSourceXIndex BBSourceYIndex BBWarpBase
> > BBWidthIndex BBXTableIndex BEBitBltIndex BinaryPoint BlueIndex
> > ColorMapFixedPart ColorMapIndexedPart ColorMapNewStyle ColorMapPresent
> > CrossedX EndOfRun FixedPt1 FormBitsIndex FormDepthIndex FormHeightIndex
> > FormWidthIndex GreenIndex OpTable OpTableSize RedIndex'
> >         poolDictionaries: ''
> >         category: 'VMMaker-Interpreter'!
> >
> > + !BitBltSimulation commentStamp: 'nice 10/31/2020 23:39' prior: 0!
> > - !BitBltSimulation commentStamp: 'tpr 3/25/2013 16:50' prior: 0!
> >   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
> >         35 alphaBlendScaled: sourceWord with:   "unused here - only used
> > by FXBlt"
> >         36 alphaBlendScaled: sourceWord with:   "unused here - only used
> > by FXBlt"
> >         37 rgbMul: sourceWord with: destinationWord
> >         38 pixSwap: sourceWord with: destinationWord
> >         39 pixClear: sourceWord with: destinationWord
> >         40 fixAlpha: sourceWord with: destinationWord
> >         41 rgbComponentAlpha: sourceWord with: destinationWord
> > +       42 alphaScale: ignoredSourceWord with: destinationWord
> > +       43 alphaUnscale: ignoredSourceWord with: destinationWord
> > +       44      alphaBlendUnscaled: 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
> >   !
> >
> > Item was changed:
> >   ----- Method: BitBltSimulation class>>initializeRuleTable (in category
> > 'initialization') -----
> >   initializeRuleTable
> >         "BitBltSimulation initializeRuleTable"
> >         "**WARNING** You MUST change initBBOpTable if you change this"
> >         OpTable := #(
> >                 "0" clearWord:with:
> >                 "1" bitAnd:with:
> >                 "2" bitAndInvert:with:
> >                 "3" sourceWord:with:
> >                 "4" bitInvertAnd:with:
> >                 "5" destinationWord:with:
> >                 "6" bitXor:with:
> >                 "7" bitOr:with:
> >                 "8" bitInvertAndInvert:with:
> >                 "9" bitInvertXor:with:
> >                 "10" bitInvertDestination:with:
> >                 "11" bitOrInvert:with:
> >                 "12" bitInvertSource:with:
> >                 "13" bitInvertOr:with:
> >                 "14" bitInvertOrInvert:with:
> >                 "15" destinationWord:with:
> >                 "16" destinationWord:with: "unused - was old paint"
> >                 "17" destinationWord:with: "unused - was old mask"
> >                 "18" addWord:with:
> >                 "19" subWord:with:
> >                 "20" rgbAdd:with:
> >                 "21" rgbSub:with:
> >                 "22" OLDrgbDiff:with:
> >                 "23" OLDtallyIntoMap:with:
> >                 "24" alphaBlend:with:
> >                 "25" pixPaint:with:
> >                 "26" pixMask:with:
> >                 "27" rgbMax:with:
> >                 "28" rgbMin:with:
> >                 "29" rgbMinInvert:with:
> >                 "30" alphaBlendConst:with:
> >                 "31" alphaPaintConst:with:
> >                 "32" rgbDiff:with:
> >                 "33" tallyIntoMap:with:
> >                 "34" alphaBlendScaled:with:
> >
> >                 "35" alphaBlendScaled:with:     "unused here - only used
> > by FXBlt"
> >                 "36" alphaBlendScaled:with:     "unused here - only used
> > by FXBlt"
> >                 "37" rgbMul:with:
> >                 "38" pixSwap:with:
> >                 "39" pixClear:with:
> >                 "40" fixAlpha:with:
> >                 "41" rgbComponentAlpha:with:
> > +               "42" alphaScale:with:
> > +               "43" alphaUnscale:with:
> > +               "44" alphaBlendUnscaled:with:
> >         ).
> >         OpTableSize := OpTable size + 1.  "0-origin indexing"
> >   !
> >
> > Item was added:
> > + ----- Method: BitBltSimulation>>alphaBlendUnscaled:with: (in category
> > 'combination rules') -----
> > + alphaBlendUnscaled: sourceWord with: destinationWord
> > +       "Blend sourceWord with destinationWord using the alpha value from
> > both sourceWord and destinationWord.
> > +       Alpha is encoded as 0 meaning 0.0, and 255 meaning 1.0.
> > +       The alpha channel and color produced are
> > +
> > +               srcAlpha + (destAlpha*(1-srcAlpha))
> > +               (srcAlpha*srcColor + (destAlpha*(1-srcAlpha)*dstColor)) /
> > (srcAlpha + (destAlpha*(1-srcAlpha)))
> > +
> > +       In contrast to alphaBlend:with: the method does not assume that
> > destination form is opaque.
> > +       In contrast to alphaBlendScaled:with: the method does not assume
> > that colors have been pre-scaled (muliplied) by alpha channel."
> > +       | alpha blendA result blendRB blendG |
> > +       <inline: false>
> > +       <returnTypeC: 'unsigned int'>
> > +       <var: #sourceWord type: 'unsigned int'>
> > +       <var: #destinationWord type: 'unsigned int'>
> > +       <var: #blendRB type: 'unsigned int'>
> > +       <var: #blendG type: 'unsigned int'>
> > +       <var: #result type: 'unsigned int'>
> > +       <var: #alpha type: 'unsigned int'>
> > +       <var: #blendA type: 'unsigned int'>
> > +       alpha := sourceWord >> 24.  "High 8 bits of source pixel, assuming
> > ARGB encoding"
> > +       alpha = 0 ifTrue: [ ^ destinationWord ].
> > +       alpha = 255 ifTrue: [ ^ sourceWord ].
> > +
> > +       blendA := 16rFF * alpha + (16rFF - alpha * (destinationWord >>
> > 24)) + 16rFF. "blend alpha channels"
> > +       blendA := blendA + (blendA - 1 >> 8 bitAnd: 16rFF) >> 8 bitAnd:
> > 16rFF. "divide by 255"
> > +
> > +       blendRB := ((sourceWord bitAnd: 16rFF00FF) * alpha) +
> > +                               ((destinationWord bitAnd: 16rFF00FF) *
> > (blendA-alpha))
> > +                               / blendA.       "blend red and blue"
> > +
> > +       blendG := ((sourceWord bitAnd: 16r00FF00) * alpha) +
> > +                               ((destinationWord bitAnd: 16r00FF00) *
> > (blendA-alpha))
> > +                               / blendA.       "blend green"
> > +       result := (blendRB bitOr: blendG) bitOr: blendA << 24.
> > +       ^ result
> > + !
> >
> > Item was added:
> > + ----- Method: BitBltSimulation>>alphaScale:with: (in category
> > 'combination rules') -----
> > + alphaScale: sourceWord with: destinationWord
> > +       "Scale (premultiply) the destination with its alpha channel.
> > +       Note that sourceWord is ignored."
> > +       | alpha rb g |
> > +       <inline: false> "Do NOT inline this into optimized loops"
> > +       <returnTypeC: 'unsigned int'>
> > +       <var: #sourceWord type: 'unsigned int'>
> > +       <var: #destinationWord type: 'unsigned int'>
> > +       <var: #rb type: 'unsigned int'>
> > +       <var: #g type: 'unsigned int'>
> > +       <var: #alpha type: 'unsigned int'>
> > +       alpha := destinationWord >> 24.  "High 8 bits is opacity (ARGB
> > format)"
> > +       rb := ((destinationWord bitAnd: 16rFF00FF) * alpha >> 8 bitAnd:
> > 16rFF00FF). "scale red and blue components"
> > +       g := ((destinationWord bitAnd: 16r00FF00) * alpha >> 8 bitAnd:
> > 16r00FF00). "scale green component"
> > +       ^(g bitOr: rb) bitOr: (destinationWord bitAnd: 16rFF000000)
> > "recompose"!
> >
> > Item was added:
> > + ----- Method: BitBltSimulation>>alphaUnscale:with: (in category
> > 'combination rules') -----
> > + alphaUnscale: sourceWord with: destinationWord
> > +       "Unscale (divide) the destination with its alpha channel.
> > +       Note that sourceWord is ignored."
> > +       | alpha rb g rgb carry |
> > +       <inline: false> "Do NOT inline this into optimized loops"
> > +       <returnTypeC: 'unsigned int'>
> > +       <var: #sourceWord type: 'unsigned int'>
> > +       <var: #destinationWord type: 'unsigned int'>
> > +       <var: #rb type: 'unsigned int'>
> > +       <var: #g type: 'unsigned int'>
> > +       <var: #rgb type: 'unsigned int'>
> > +       <var: #alpha type: 'unsigned int'>
> > +       <var: #carry type: 'unsigned int'>
> > +       alpha := destinationWord >> 24.  "High 8 bits is opacity (ARGB
> > format)"
> > +       alpha = 0 ifTrue: [^0].
> > +       rb := (destinationWord bitAnd: 16rFF00FF) << 8 / alpha. "unscale
> > red and blue components"
> > +       g := (destinationWord bitAnd: 16r00FF00) / alpha. "unscale green
> > component"
> > +       carry := ((rb >> 8 bitAnd: 16rAA00AA) >> 1 bitOr: (rb >> 8 bitAnd:
> > 16r550055) << 1)
> > +               bitOr: ((g bitAnd: 16r00AA00) >> 1 bitOr: (g bitAnd:
> > 16r005500) << 1).
> > +       carry := (carry bitAnd: 16rCCCCCC) >> 2 bitOr: (carry bitAnd:
> > 16r333333) << 2.
> > +       carry := (carry bitAnd: 16rF0F0F0) >> 4 bitOr: (carry bitAnd:
> > 16r0F0F0F) << 4.
> > +       rgb := (rb bitAnd: 16rFF00FF) bitOr: (g << 8 bitAnd: 16r00FF00).
> > +       rgb := rgb bitOr: carry.  "saturate RGB components if division
> > overflows"
> > +       ^rgb bitOr: (destinationWord bitAnd: 16rFF000000) "restore alpha"!
> >
> > Item was changed:
> >   ----- Method: BitBltSimulation>>initBBOpTable (in category
> > 'initialize-release') -----
> >   initBBOpTable
> >         self cCode: 'opTable[0+1] = (void *)clearWordwith'.
> >         self cCode: 'opTable[1+1] = (void *)bitAndwith'.
> >         self cCode: 'opTable[2+1] = (void *)bitAndInvertwith'.
> >         self cCode: 'opTable[3+1] = (void *)sourceWordwith'.
> >         self cCode: 'opTable[4+1] = (void *)bitInvertAndwith'.
> >         self cCode: 'opTable[5+1] = (void *)destinationWordwith'.
> >         self cCode: 'opTable[6+1] = (void *)bitXorwith'.
> >         self cCode: 'opTable[7+1] = (void *)bitOrwith'.
> >         self cCode: 'opTable[8+1] = (void *)bitInvertAndInvertwith'.
> >         self cCode: 'opTable[9+1] = (void *)bitInvertXorwith'.
> >         self cCode: 'opTable[10+1] = (void *)bitInvertDestinationwith'.
> >         self cCode: 'opTable[11+1] = (void *)bitOrInvertwith'.
> >         self cCode: 'opTable[12+1] = (void *)bitInvertSourcewith'.
> >         self cCode: 'opTable[13+1] = (void *)bitInvertOrwith'.
> >         self cCode: 'opTable[14+1] = (void *)bitInvertOrInvertwith'.
> >         self cCode: 'opTable[15+1] = (void *)destinationWordwith'.
> >         self cCode: 'opTable[16+1] = (void *)destinationWordwith'.
> >         self cCode: 'opTable[17+1] = (void *)destinationWordwith'.
> >         self cCode: 'opTable[18+1] = (void *)addWordwith'.
> >         self cCode: 'opTable[19+1] = (void *)subWordwith'.
> >         self cCode: 'opTable[20+1] = (void *)rgbAddwith'.
> >         self cCode: 'opTable[21+1] = (void *)rgbSubwith'.
> >         self cCode: 'opTable[22+1] = (void *)OLDrgbDiffwith'.
> >         self cCode: 'opTable[23+1] = (void *)OLDtallyIntoMapwith'.
> >         self cCode: 'opTable[24+1] = (void *)alphaBlendwith'.
> >         self cCode: 'opTable[25+1] = (void *)pixPaintwith'.
> >         self cCode: 'opTable[26+1] = (void *)pixMaskwith'.
> >         self cCode: 'opTable[27+1] = (void *)rgbMaxwith'.
> >         self cCode: 'opTable[28+1] = (void *)rgbMinwith'.
> >         self cCode: 'opTable[29+1] = (void *)rgbMinInvertwith'.
> >         self cCode: 'opTable[30+1] = (void *)alphaBlendConstwith'.
> >         self cCode: 'opTable[31+1] = (void *)alphaPaintConstwith'.
> >         self cCode: 'opTable[32+1] = (void *)rgbDiffwith'.
> >         self cCode: 'opTable[33+1] = (void *)tallyIntoMapwith'.
> >         self cCode: 'opTable[34+1] = (void *)alphaBlendScaledwith'.
> >         self cCode: 'opTable[35+1] = (void *)alphaBlendScaledwith'.
> >         self cCode: 'opTable[36+1] = (void *)alphaBlendScaledwith'.
> >         self cCode: 'opTable[37+1] = (void *)rgbMulwith'.
> >         self cCode: 'opTable[38+1] = (void *)pixSwapwith'.
> >         self cCode: 'opTable[39+1] = (void *)pixClearwith'.
> >         self cCode: 'opTable[40+1] = (void *)fixAlphawith'.
> > +       self cCode: 'opTable[41+1] = (void *)rgbComponentAlphawith'.
> > +       self cCode: 'opTable[42+1] = (void *)alphaScalewith'.
> > +       self cCode: 'opTable[43+1] = (void *)alphaUnscalewith'.
> > +       self cCode: 'opTable[44+1] = (void *)alphaBlendUnscaledwith'.!
> > -       self cCode: 'opTable[41+1] = (void *)rgbComponentAlphawith'.!
> >
> >