[Vm-dev] VM Maker: VMMaker.oscog-nice.3170.mcz
commits at source.squeak.org
commits at source.squeak.org
Thu Feb 24 13:49:01 UTC 2022
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-nice.3170.mcz
==================== Summary ====================
Name: VMMaker.oscog-nice.3170
Author: nice
Time: 24 February 2022, 2:48:39.990237 pm
UUID: 6b851cd8-b485-1047-acfd-8adee37e3660
Ancestors: VMMaker.oscog-nice.3169
Revise the 3 new BitBlt rules again
(see https://github.com/OpenSmalltalk/opensmalltalk-vm/issues/505)
- use a proper division by 255 (factor alpha/255) in alphaScale:with: instead of approximate factor alpha/256 previously
- use a proper rounding (by adding 16r80 before the division by 255) in alphaScale:with:
- split the unscale ops in 3 separate r/g/b channels, otherwise, when grouping rb, the division by alpha will leak red bits not only on green components but also on blue
- fixup the carry used for saturating the rbg components in case of 16rFF overflow in alphaUnscale:with:
Note: division by 255 can be checked thru this snippet (should answer 0):
(0 to: 16rFF squared) inject: 0 into:
[:max :num |
| rat |
rat := num + 16r80. "+ 16r80 for rounding"
rat := rat + (rat - 1 >> 8 bitAnd: 16rFF) >> 8 bitAnd: 16rFF. "divide by 255"
((num/255) rounded - rat) abs max: max].
=============== Diff against VMMaker.oscog-nice.3169 ===============
Item was changed:
----- 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 blendR blendB blendG |
- | alpha blendA result blendRB blendG |
<inline: false>
<returnTypeC: 'unsigned int'>
<var: 'sourceWord' type: #'unsigned int'>
<var: 'destinationWord' type: #'unsigned int'>
+ <var: 'blendA' type: #'unsigned int'>
+ <var: 'blendR' type: #'unsigned int'>
- <var: 'blendRB' type: #'unsigned int'>
<var: 'blendG' type: #'unsigned int'>
+ <var: 'blendB' 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)) + 16r80. "blend alpha channels"
- blendA := 16rFF * alpha + (16rFF - alpha * (destinationWord >> 24)) + 16rFF. "blend alpha channels"
blendA := blendA + (blendA - 1 >> 8 bitAnd: 16rFF) >> 8 bitAnd: 16rFF. "divide by 255"
+ blendR := ((sourceWord bitAnd: 16rFF0000) * alpha) +
+ ((destinationWord bitAnd: 16rFF0000) * (blendA-alpha))
+ +(blendA<<15)
+ // blendA bitAnd: 16rFF0000. "blend red"
+
- blendRB := ((sourceWord bitAnd: 16rFF00FF) * alpha) +
- ((destinationWord bitAnd: 16rFF00FF) * (blendA-alpha))
- / blendA bitAnd: 16rFF00FF. "blend red and blue"
-
blendG := ((sourceWord bitAnd: 16r00FF00) * alpha) +
((destinationWord bitAnd: 16r00FF00) * (blendA-alpha))
+ +(blendA<<7)
+ // blendA bitAnd: 16r00FF00. "blend green"
+
+ blendB := ((sourceWord bitAnd: 16r0000FF) * alpha) +
+ ((destinationWord bitAnd: 16r0000FF) * (blendA-alpha))
+ +(blendA>>1)
+ // blendA bitAnd: 16r0000FF. "blend blue"
+
+ result := ((blendR bitOr: blendB) bitOr: blendG) bitOr: blendA << 24.
- / blendA bitAnd: 16r00FF00. "blend green"
- result := (blendRB bitOr: blendG) bitOr: blendA << 24.
^ result
!
Item was changed:
----- 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 + 16r800080. "scale red and blue components"
+ rb := rb + (rb - 16r010001 >> 8 bitAnd: 16rFF00FF) >> 8 bitAnd: 16rFF00FF. "divide by 255"
+ g := (destinationWord bitAnd: 16r00FF00) * alpha + 16r008000. "scale green component"
+ g := g + (g - 16r000100 >> 8 bitAnd: 16r00FF00) >> 8 bitAnd: 16r00FF00. "divide by 255"
- 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 changed:
----- 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 r b g rgb carry |
- | 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: 'r' type: #'unsigned int'>
- <var: 'rb' type: #'unsigned int'>
<var: 'g' type: #'unsigned int'>
+ <var: 'b' 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].
+ r := (destinationWord bitAnd: 16rFF0000) * 255 + (alpha+1<<15) // alpha. "unscale red components"
+ g := (destinationWord bitAnd: 16r00FF00) * 255 + (alpha+1<<7) // alpha. "unscale green component"
+ b := (destinationWord bitAnd: 16r0000FF) * 255 + (alpha+1>>1) // alpha. "unscale blue components"
+ carry := (((r bitAnd: 16rFF000000) bitOr: (g bitAnd: 16rFF0000)) bitOr: (b bitAnd: 16rFF00)) >> 8.
+ carry := carry bitOr: ((carry bitAnd: 16rAAAAAA) >> 1 bitOr: (carry bitAnd: 16r555555) << 1).
+ carry := carry bitOr: ((carry bitAnd: 16rCCCCCC) >> 2 bitOr: (carry bitAnd: 16r333333) << 2).
+ carry := carry bitOr: ((carry bitAnd: 16rF0F0F0) >> 4 bitOr: (carry bitAnd: 16r0F0F0F) << 4).
+ rgb := ((r bitAnd: 16rFF0000) bitOr: (g bitAnd: 16r00FF00)) bitOr: (b bitAnd: 16r0000FF).
- 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"!
More information about the Vm-dev
mailing list