diff options
| author | Přemysl Eric Janouch <p@janouch.name> | 2021-07-15 01:43:13 +0200 | 
|---|---|---|
| committer | Přemysl Eric Janouch <p@janouch.name> | 2021-07-15 01:49:37 +0200 | 
| commit | a927713a81321f84b1a1cd1675a142bf931ae510 (patch) | |
| tree | da4d43bad02534bbe8f8cca4c81a3e6a615334b2 /prototypes | |
| parent | 5ae8c24b8d580a09f4b95742230e64f135e52635 (diff) | |
| download | haven-a927713a81321f84b1a1cd1675a142bf931ae510.tar.gz haven-a927713a81321f84b1a1cd1675a142bf931ae510.tar.xz haven-a927713a81321f84b1a1cd1675a142bf931ae510.zip | |
xgb-image: support 10-bit colours
Apparently, a DefaultDepth 30 Xserver won't do translucency.
Diffstat (limited to 'prototypes')
| -rw-r--r-- | prototypes/xgb-image.go | 97 | 
1 files changed, 71 insertions, 26 deletions
| diff --git a/prototypes/xgb-image.go b/prototypes/xgb-image.go index fce0ab1..c6ab02c 100644 --- a/prototypes/xgb-image.go +++ b/prototypes/xgb-image.go @@ -14,6 +14,7 @@ import (  	"github.com/BurntSushi/xgb/xproto"  	"image" +	"image/color"  	_ "image/gif"  	_ "image/jpeg"  	_ "image/png" @@ -26,6 +27,47 @@ import "C"  func F64ToFixed(f float64) render.Fixed { return render.Fixed(f * 65536) }  func FixedToF64(f render.Fixed) float64 { return float64(f) / 65536 } +var formats = map[byte]struct { +	format    render.Directformat +	transform func(color.Color) uint32 +}{ +	32: { +		format: render.Directformat{ +			RedShift:   16, +			RedMask:    0xff, +			GreenShift: 8, +			GreenMask:  0xff, +			BlueShift:  0, +			BlueMask:   0xff, +			AlphaShift: 24, +			AlphaMask:  0xff, +		}, +		transform: func(color color.Color) uint32 { +			r, g, b, a := color.RGBA() +			return (a>>8)<<24 | (r>>8)<<16 | (g>>8)<<8 | (b >> 8) +		}, +	}, +	30: { +		/* +			// Alpha makes compositing unbearably slow. +			AlphaShift: 30, +			AlphaMask:  0x3, +		*/ +		format: render.Directformat{ +			RedShift:   20, +			RedMask:    0x3ff, +			GreenShift: 10, +			GreenMask:  0x3ff, +			BlueShift:  0, +			BlueMask:   0x3ff, +		}, +		transform: func(color color.Color) uint32 { +			r, g, b, a := color.RGBA() +			return (a>>14)<<30 | (r>>6)<<20 | (g>>6)<<10 | (b >> 6) +		}, +	}, +} +  func main() {  	/*  		pf, err := os.Create("pprof.out") @@ -63,18 +105,35 @@ func main() {  	screen := setup.DefaultScreen(X)  	visual, depth := screen.RootVisual, screen.RootDepth -	// TODO: We should check that we find it, though we don't /need/ alpha here, -	// it's just a minor improvement--affects the backpixel value. + +	// Only go for 10-bit when the picture can make use of that range. +	prefer30 := false +	switch img.(type) { +	case *image.Gray16, *image.RGBA64, *image.NRGBA64: +		prefer30 = true +	} + +	// XXX: We don't /need/ alpha here, it's just a minor improvement--affects +	// the backpixel value. (And we reject it in 30-bit depth anyway.)  	for _, i := range screen.AllowedDepths {  		for _, v := range i.Visuals {  			// TODO: Could/should check other parameters. -			if i.Depth == 32 && v.Class == xproto.VisualClassTrueColor { +			if v.Class != xproto.VisualClassTrueColor { +				continue +			} +			if prefer30 && i.Depth == 30 || +				!prefer30 && i.Depth == 32 {  				visual, depth = v.VisualId, i.Depth  				break  			}  		}  	} +	format, ok := formats[depth] +	if !ok { +		log.Fatalln("unsupported bit depth") +	} +  	mid, err := xproto.NewColormapId(X)  	if err != nil {  		log.Fatalln(err) @@ -92,7 +151,7 @@ func main() {  	_ = xproto.CreateWindow(X, depth, wid, screen.Root,  		0, 0, 500, 500, 0, xproto.WindowClassInputOutput,  		visual, xproto.CwBackPixel|xproto.CwBorderPixel|xproto.CwEventMask| -			xproto.CwColormap, []uint32{0x80808080, 0, +			xproto.CwColormap, []uint32{format.transform(color.Alpha{0x80}), 0,  			xproto.EventMaskStructureNotify | xproto.EventMaskExposure,  			uint32(mid)}) @@ -132,7 +191,7 @@ func main() {  	// setup.BitmapFormatScanline{Pad,Unit} and setup.BitmapFormatBitOrder  	// don't interest us here since we're only using Z format pixmaps.  	for _, pf := range setup.PixmapFormats { -		if pf.Depth == 32 { +		if pf.Depth == depth {  			if pf.BitsPerPixel != 32 || pf.ScanlinePad != 32 {  				log.Fatalln("unsuported X server")  			} @@ -143,28 +202,18 @@ func main() {  	if err != nil {  		log.Fatalln(err)  	} -	_ = xproto.CreatePixmap(X, 32, pixid, xproto.Drawable(screen.Root), +	_ = xproto.CreatePixmap(X, depth, pixid, xproto.Drawable(screen.Root),  		uint16(img.Bounds().Dx()), uint16(img.Bounds().Dy()))  	var bgraFormat render.Pictformat -	wanted := render.Directformat{ -		RedShift:   16, -		RedMask:    0xff, -		GreenShift: 8, -		GreenMask:  0xff, -		BlueShift:  0, -		BlueMask:   0xff, -		AlphaShift: 24, -		AlphaMask:  0xff, -	}  	for _, pf := range pformats.Formats { -		if pf.Depth == 32 && pf.Direct == wanted { +		if pf.Depth == depth && pf.Direct == format.format {  			bgraFormat = pf.Id  			break  		}  	}  	if bgraFormat == 0 { -		log.Fatalln("ARGB format not found") +		log.Fatalln("picture format not found")  	}  	// We could also look for the inverse pictformat. @@ -202,14 +251,12 @@ func main() {  		row := make([]byte, bounds.Dx()*4)  		for y := bounds.Min.Y; y < bounds.Max.Y; y++ {  			for x := bounds.Min.X; x < bounds.Max.X; x++ { -				r, g, b, a := img.At(x, y).RGBA() -				encoding.PutUint32(row[x*4:], -					(a>>8)<<24|(r>>8)<<16|(g>>8)<<8|(b>>8)) +				encoding.PutUint32(row[x*4:], format.transform(img.At(x, y)))  			}  			_ = xproto.PutImage(X, xproto.ImageFormatZPixmap,  				xproto.Drawable(pixid), cid, uint16(bounds.Dx()), 1,  				0, int16(y), -				0, 32, row) +				0, depth, row)  		}  	} else {  		rep, err := shm.QueryVersion(X).Reply() @@ -242,9 +289,7 @@ func main() {  		for y := bounds.Min.Y; y < bounds.Max.Y; y++ {  			row := data[y*bounds.Dx()*4:]  			for x := bounds.Min.X; x < bounds.Max.X; x++ { -				r, g, b, a := img.At(x, y).RGBA() -				encoding.PutUint32(row[x*4:], -					(a>>8)<<24|(r>>8)<<16|(g>>8)<<8|(b>>8)) +				encoding.PutUint32(row[x*4:], format.transform(img.At(x, y)))  			}  		} @@ -262,7 +307,7 @@ func main() {  		_ = shm.PutImage(X, xproto.Drawable(pixid), cid,  			uint16(bounds.Dx()), uint16(bounds.Dy()), 0, 0,  			uint16(bounds.Dx()), uint16(bounds.Dy()), 0, 0, -			32, xproto.ImageFormatZPixmap, +			depth, xproto.ImageFormatZPixmap,  			0 /* SendEvent */, segid, 0 /* Offset */)  	} | 
