[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