github.com/thommil/tge-gl@v0.0.0-20190313100017-83d8f10f8fae/gl.go (about)

     1  // Copyright (c) 2019 Thomas MILLET. All rights reserved.
     2  
     3  // Package gl defines tge-gl API
     4  package gl
     5  
     6  import (
     7  	binary "encoding/binary"
     8  	unsafe "unsafe"
     9  
    10  	tge "github.com/thommil/tge"
    11  )
    12  
    13  // Name name of the plugin
    14  const Name = "gl"
    15  
    16  var _pluginInstance = &plugin{}
    17  var nativeEndian binary.ByteOrder
    18  
    19  func init() {
    20  	tge.Register(_pluginInstance)
    21  
    22  	buf := [2]byte{}
    23  	*(*uint16)(unsafe.Pointer(&buf[0])) = uint16(0xABCD)
    24  	switch buf {
    25  	case [2]byte{0xAB, 0xCD}:
    26  		nativeEndian = binary.BigEndian
    27  	default:
    28  		nativeEndian = binary.LittleEndian
    29  	}
    30  }
    31  
    32  func (p *plugin) GetName() string {
    33  	return Name
    34  }
    35  
    36  // Byte buffer array singleton, allocate 1mB at startup
    37  var byteArrayBuffer = make([]byte, 0)
    38  var byteArrayBufferExtendFactor = 1
    39  
    40  func getByteArrayBuffer(size int) []byte {
    41  	if size > len(byteArrayBuffer) {
    42  		for (1024 * 1024 * byteArrayBufferExtendFactor) < size {
    43  			byteArrayBufferExtendFactor++
    44  		}
    45  		byteArrayBuffer = make([]byte, (1024 * 1024 * byteArrayBufferExtendFactor))
    46  	}
    47  	return byteArrayBuffer[:size]
    48  }
    49  
    50  // Uint16ToBytes convert uint16 array to byte array
    51  // depending on host endianness
    52  func Uint16ToBytes(values []uint16) []byte {
    53  	b := getByteArrayBuffer(2 * len(values))
    54  
    55  	if nativeEndian == binary.LittleEndian {
    56  		for i, v := range values {
    57  			u := *(*uint16)(unsafe.Pointer(&v))
    58  			b[2*i+0] = byte(u)
    59  			b[2*i+1] = byte(u >> 8)
    60  		}
    61  	} else {
    62  		for i, v := range values {
    63  			u := *(*uint16)(unsafe.Pointer(&v))
    64  			b[2*i+0] = byte(u >> 8)
    65  			b[2*i+1] = byte(u)
    66  		}
    67  	}
    68  
    69  	return b
    70  }
    71  
    72  // Uint32ToBytes convert uint32 array to byte array
    73  // depending on host endianness
    74  func Uint32ToBytes(values []uint32) []byte {
    75  	b := getByteArrayBuffer(4 * len(values))
    76  
    77  	if nativeEndian == binary.LittleEndian {
    78  		for i, v := range values {
    79  			u := *(*uint32)(unsafe.Pointer(&v))
    80  			b[2*i+0] = byte(u)
    81  			b[2*i+1] = byte(u >> 8)
    82  			b[4*i+2] = byte(u >> 16)
    83  			b[4*i+3] = byte(u >> 24)
    84  		}
    85  	} else {
    86  		for i, v := range values {
    87  			u := *(*uint32)(unsafe.Pointer(&v))
    88  			b[4*i+0] = byte(u >> 24)
    89  			b[4*i+1] = byte(u >> 16)
    90  			b[4*i+2] = byte(u >> 8)
    91  			b[4*i+3] = byte(u)
    92  		}
    93  	}
    94  
    95  	return b
    96  }
    97  
    98  // Int16ToBytes convert int16 array to byte array
    99  // depending on host endianness
   100  func Int16ToBytes(values []uint16) []byte {
   101  	b := getByteArrayBuffer(2 * len(values))
   102  
   103  	if nativeEndian == binary.LittleEndian {
   104  		for i, v := range values {
   105  			u := *(*int16)(unsafe.Pointer(&v))
   106  			b[2*i+0] = byte(u)
   107  			b[2*i+1] = byte(u >> 8)
   108  		}
   109  	} else {
   110  		for i, v := range values {
   111  			u := *(*int16)(unsafe.Pointer(&v))
   112  			b[2*i+0] = byte(u >> 8)
   113  			b[2*i+1] = byte(u)
   114  		}
   115  	}
   116  
   117  	return b
   118  }
   119  
   120  // Int32ToBytes convert int32 array to byte array
   121  // depending on host endianness
   122  func Int32ToBytes(values []uint32) []byte {
   123  	b := getByteArrayBuffer(4 * len(values))
   124  
   125  	if nativeEndian == binary.LittleEndian {
   126  		for i, v := range values {
   127  			u := *(*int32)(unsafe.Pointer(&v))
   128  			b[2*i+0] = byte(u)
   129  			b[2*i+1] = byte(u >> 8)
   130  			b[4*i+2] = byte(u >> 16)
   131  			b[4*i+3] = byte(u >> 24)
   132  		}
   133  	} else {
   134  		for i, v := range values {
   135  			u := *(*int32)(unsafe.Pointer(&v))
   136  			b[4*i+0] = byte(u >> 24)
   137  			b[4*i+1] = byte(u >> 16)
   138  			b[4*i+2] = byte(u >> 8)
   139  			b[4*i+3] = byte(u)
   140  		}
   141  	}
   142  
   143  	return b
   144  }
   145  
   146  // Float32ToBytes convert float32 array to byte array
   147  // depending on host endianness
   148  func Float32ToBytes(values []float32) []byte {
   149  	b := getByteArrayBuffer(4 * len(values))
   150  
   151  	if nativeEndian == binary.LittleEndian {
   152  		for i, v := range values {
   153  			u := *(*uint32)(unsafe.Pointer(&v))
   154  			b[4*i+0] = byte(u)
   155  			b[4*i+1] = byte(u >> 8)
   156  			b[4*i+2] = byte(u >> 16)
   157  			b[4*i+3] = byte(u >> 24)
   158  		}
   159  	} else {
   160  		for i, v := range values {
   161  			u := *(*uint32)(unsafe.Pointer(&v))
   162  			b[4*i+0] = byte(u >> 24)
   163  			b[4*i+1] = byte(u >> 16)
   164  			b[4*i+2] = byte(u >> 8)
   165  			b[4*i+3] = byte(u)
   166  		}
   167  	}
   168  
   169  	return b
   170  }
   171  
   172  // Float64ToBytes convert float64 array to byte array
   173  // depending on host endianness
   174  func Float64ToBytes(values []float64) []byte {
   175  	b := getByteArrayBuffer(8 * len(values))
   176  
   177  	if nativeEndian == binary.LittleEndian {
   178  		for i, v := range values {
   179  			u := *(*uint64)(unsafe.Pointer(&v))
   180  			b[8*i+0] = byte(u)
   181  			b[8*i+1] = byte(u >> 8)
   182  			b[8*i+2] = byte(u >> 16)
   183  			b[8*i+3] = byte(u >> 24)
   184  			b[8*i+4] = byte(u >> 32)
   185  			b[8*i+5] = byte(u >> 40)
   186  			b[8*i+6] = byte(u >> 48)
   187  			b[8*i+7] = byte(u >> 56)
   188  		}
   189  	} else {
   190  		for i, v := range values {
   191  			u := *(*uint64)(unsafe.Pointer(&v))
   192  			b[8*i+0] = byte(u >> 56)
   193  			b[8*i+1] = byte(u >> 48)
   194  			b[8*i+2] = byte(u >> 40)
   195  			b[8*i+3] = byte(u >> 32)
   196  			b[8*i+4] = byte(u >> 24)
   197  			b[8*i+5] = byte(u >> 16)
   198  			b[8*i+6] = byte(u >> 8)
   199  			b[8*i+7] = byte(u)
   200  		}
   201  	}
   202  
   203  	return b
   204  }
   205  
   206  // PointerToBytes allows to revover Byte[] from a pointer, useful for ports (ex: G3N)
   207  func PointerToBytes(data interface{}, size int) []byte {
   208  	switch data.(type) {
   209  	case *uint8:
   210  		b := getByteArrayBuffer(size)
   211  		for i := 0; i < size; i++ {
   212  			b[i] = *(*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(data.(*uint8))) + uintptr(i)))
   213  		}
   214  		return b
   215  	case *uint16:
   216  		b := getByteArrayBuffer(2 * size)
   217  		if nativeEndian == binary.LittleEndian {
   218  			for i := 0; i < size; i++ {
   219  				v := *(*uint16)(unsafe.Pointer(uintptr(unsafe.Pointer(data.(*uint16))) + uintptr(i*4)))
   220  				u := *(*uint16)(unsafe.Pointer(&v))
   221  				b[2*i+0] = byte(u)
   222  				b[2*i+1] = byte(u >> 8)
   223  			}
   224  		} else {
   225  			for i := 0; i < size; i++ {
   226  				v := *(*uint16)(unsafe.Pointer(uintptr(unsafe.Pointer(data.(*uint16))) + uintptr(i*4)))
   227  				u := *(*uint16)(unsafe.Pointer(&v))
   228  				b[2*i+0] = byte(u >> 8)
   229  				b[2*i+1] = byte(u)
   230  			}
   231  		}
   232  		return b
   233  	case *uint32:
   234  		b := getByteArrayBuffer(4 * size)
   235  		if nativeEndian == binary.LittleEndian {
   236  			for i := 0; i < size; i++ {
   237  				v := *(*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(data.(*uint32))) + uintptr(i*4)))
   238  				u := *(*uint32)(unsafe.Pointer(&v))
   239  				b[4*i+0] = byte(u)
   240  				b[4*i+1] = byte(u >> 8)
   241  				b[4*i+2] = byte(u >> 16)
   242  				b[4*i+3] = byte(u >> 24)
   243  			}
   244  		} else {
   245  			for i := 0; i < size; i++ {
   246  				v := *(*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(data.(*uint32))) + uintptr(i*4)))
   247  				u := *(*uint32)(unsafe.Pointer(&v))
   248  				b[4*i+0] = byte(u >> 24)
   249  				b[4*i+1] = byte(u >> 16)
   250  				b[4*i+2] = byte(u >> 8)
   251  				b[4*i+3] = byte(u)
   252  			}
   253  		}
   254  		return b
   255  	case *float32:
   256  		b := getByteArrayBuffer(4 * size)
   257  		if nativeEndian == binary.LittleEndian {
   258  			for i := 0; i < size; i++ {
   259  				v := *(*float32)(unsafe.Pointer(uintptr(unsafe.Pointer(data.(*float32))) + uintptr(i*4)))
   260  				u := *(*uint32)(unsafe.Pointer(&v))
   261  				b[4*i+0] = byte(u)
   262  				b[4*i+1] = byte(u >> 8)
   263  				b[4*i+2] = byte(u >> 16)
   264  				b[4*i+3] = byte(u >> 24)
   265  			}
   266  		} else {
   267  			for i := 0; i < size; i++ {
   268  				v := *(*float32)(unsafe.Pointer(uintptr(unsafe.Pointer(data.(*float32))) + uintptr(i*4)))
   269  				u := *(*uint32)(unsafe.Pointer(&v))
   270  				b[4*i+0] = byte(u >> 24)
   271  				b[4*i+1] = byte(u >> 16)
   272  				b[4*i+2] = byte(u >> 8)
   273  				b[4*i+3] = byte(u)
   274  			}
   275  		}
   276  		return b
   277  	case *float64:
   278  		b := getByteArrayBuffer(8 * size)
   279  		if nativeEndian == binary.LittleEndian {
   280  			for i := 0; i < size; i++ {
   281  				v := *(*float64)(unsafe.Pointer(uintptr(unsafe.Pointer(data.(*float64))) + uintptr(i*8)))
   282  				u := *(*uint64)(unsafe.Pointer(&v))
   283  				b[8*i+0] = byte(u)
   284  				b[8*i+1] = byte(u >> 8)
   285  				b[8*i+2] = byte(u >> 16)
   286  				b[8*i+3] = byte(u >> 24)
   287  				b[8*i+4] = byte(u >> 32)
   288  				b[8*i+5] = byte(u >> 40)
   289  				b[8*i+6] = byte(u >> 48)
   290  				b[8*i+7] = byte(u >> 56)
   291  			}
   292  		} else {
   293  			for i := 0; i < size; i++ {
   294  				v := *(*float64)(unsafe.Pointer(uintptr(unsafe.Pointer(data.(*float64))) + uintptr(i*8)))
   295  				u := *(*uint64)(unsafe.Pointer(&v))
   296  				b[8*i+0] = byte(u >> 56)
   297  				b[8*i+1] = byte(u >> 48)
   298  				b[8*i+2] = byte(u >> 40)
   299  				b[8*i+3] = byte(u >> 32)
   300  				b[8*i+4] = byte(u >> 24)
   301  				b[8*i+5] = byte(u >> 16)
   302  				b[8*i+6] = byte(u >> 8)
   303  				b[8*i+7] = byte(u)
   304  			}
   305  		}
   306  		return b
   307  	}
   308  	return nil
   309  }