github.com/racerxdl/gonx@v0.0.0-20210103083128-c5afc43bcbd2/services/display/blit.go (about)

     1  package display
     2  
     3  import (
     4  	"unsafe"
     5  )
     6  
     7  func pdep(mask, value uint32) uint32 {
     8  	out := uint32(0)
     9  	for shift := uint32(0); shift < 32; shift++ {
    10  		bit := uint32(1 << shift)
    11  		if mask&bit > 0 {
    12  			if value&1 > 0 {
    13  				out |= bit
    14  			}
    15  			value >>= 1
    16  		}
    17  	}
    18  	return out
    19  }
    20  
    21  //go:inline
    22  func swizzleX(v uint32) uint32 {
    23  	return pdep(^uint32(0x7B4), v)
    24  }
    25  
    26  //go:inline
    27  func swizzleY(v uint32) uint32 {
    28  	return pdep(0x7B4, v)
    29  }
    30  
    31  //go:inline
    32  func setUint32(buffer []byte, idx uint32, v uint32) {
    33  	*(*uint32)(unsafe.Pointer(&buffer[idx*4])) = v
    34  }
    35  
    36  //go:inline
    37  func getUint32(buffer []byte, idx uint32) uint32 {
    38  	return *(*uint32)(unsafe.Pointer(&buffer[idx*4]))
    39  }
    40  
    41  //go:nobounds
    42  func GFXSlowSwizzlingBlit(buffer []byte, image []byte, w, h, tx, ty int) {
    43  	const tileHeight = 128
    44  	const paddedWidth = tileHeight * 10
    45  
    46  	x0 := uint32(tx)
    47  	y0 := uint32(ty)
    48  	x1 := x0 + uint32(w)
    49  	y1 := y0 + uint32(h)
    50  
    51  	// we're doing this in pixels - should just shift the swizzles instead
    52  	offsX0 := swizzleX(x0)
    53  	offsY := swizzleY(y0)
    54  	XMask := swizzleX(^uint32(0))
    55  	YMask := swizzleY(^uint32(0))
    56  	IncrY := swizzleX(paddedWidth)
    57  
    58  	// step offs_x0 to the right row of tiles
    59  	offsX0 += IncrY * (y0 / tileHeight)
    60  
    61  	srcPos := uint32(0)
    62  
    63  	for y := uint32(0); y < y1; y++ {
    64  		offsX := offsX0
    65  
    66  		for x := uint32(0); x < x1; x++ {
    67  			pixel := getUint32(image, srcPos)
    68  			srcPos++
    69  			setUint32(buffer, offsY+offsX, pixel)
    70  			offsX = (offsX - XMask) & XMask
    71  		}
    72  
    73  		offsY = (offsY - YMask) & YMask
    74  		if offsY == 0 {
    75  			offsX0 += IncrY // wrap into next tile row
    76  		}
    77  	}
    78  }