twitchapon-anim

Basic Twitchapon Receiver/Visuals
git clone git://bsandro.tech/twitchapon-anim
Log | Files | Refs | README | LICENSE

conversions_notwindows.go (2757B)


      1 // SPDX-License-Identifier: MIT
      2 
      3 // +build !windows
      4 
      5 package gl
      6 
      7 import (
      8 	"fmt"
      9 	"reflect"
     10 	"strings"
     11 	"unsafe"
     12 )
     13 
     14 // #include <stdlib.h>
     15 import "C"
     16 
     17 // Ptr takes a slice or pointer (to a singular scalar value or the first
     18 // element of an array or slice) and returns its GL-compatible address.
     19 //
     20 // For example:
     21 //
     22 // 	var data []uint8
     23 // 	...
     24 // 	gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0]))
     25 func Ptr(data interface{}) unsafe.Pointer {
     26 	if data == nil {
     27 		return unsafe.Pointer(nil)
     28 	}
     29 	var addr unsafe.Pointer
     30 	switch v := data.(type) {
     31 	case *uint8:
     32 		addr = unsafe.Pointer(v)
     33 	case *uint16:
     34 		addr = unsafe.Pointer(v)
     35 	case *float32:
     36 		addr = unsafe.Pointer(v)
     37 	case []uint8:
     38 		addr = unsafe.Pointer(&v[0])
     39 	case []uint16:
     40 		addr = unsafe.Pointer(&v[0])
     41 	case []float32:
     42 		addr = unsafe.Pointer(&v[0])
     43 	default:
     44 		panic(fmt.Errorf("unsupported type %T; must be a slice or pointer to a singular scalar value or the first element of an array or slice", v))
     45 	}
     46 	return addr
     47 }
     48 
     49 // Str takes a null-terminated Go string and returns its GL-compatible address.
     50 // This function reaches into Go string storage in an unsafe way so the caller
     51 // must ensure the string is not garbage collected.
     52 func Str(str string) *uint8 {
     53 	if !strings.HasSuffix(str, "\x00") {
     54 		panic("str argument missing null terminator: " + str)
     55 	}
     56 	header := (*reflect.StringHeader)(unsafe.Pointer(&str))
     57 	return (*uint8)(unsafe.Pointer(header.Data))
     58 }
     59 
     60 // GoStr takes a null-terminated string returned by OpenGL and constructs a
     61 // corresponding Go string.
     62 func GoStr(cstr *uint8) string {
     63 	return C.GoString((*C.char)(unsafe.Pointer(cstr)))
     64 }
     65 
     66 // Strs takes a list of Go strings (with or without null-termination) and
     67 // returns their C counterpart.
     68 //
     69 // The returned free function must be called once you are done using the strings
     70 // in order to free the memory.
     71 //
     72 // If no strings are provided as a parameter this function will panic.
     73 func Strs(strs ...string) (cstrs **uint8, free func()) {
     74 	if len(strs) == 0 {
     75 		panic("Strs: expected at least 1 string")
     76 	}
     77 
     78 	// Allocate a contiguous array large enough to hold all the strings' contents.
     79 	n := 0
     80 	for i := range strs {
     81 		n += len(strs[i])
     82 	}
     83 	data := C.malloc(C.size_t(n))
     84 
     85 	// Copy all the strings into data.
     86 	dataSlice := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
     87 		Data: uintptr(data),
     88 		Len:  n,
     89 		Cap:  n,
     90 	}))
     91 	css := make([]*uint8, len(strs)) // Populated with pointers to each string.
     92 	offset := 0
     93 	for i := range strs {
     94 		copy(dataSlice[offset:offset+len(strs[i])], strs[i][:]) // Copy strs[i] into proper data location.
     95 		css[i] = (*uint8)(unsafe.Pointer(&dataSlice[offset]))   // Set a pointer to it.
     96 		offset += len(strs[i])
     97 	}
     98 
     99 	return (**uint8)(&css[0]), func() { C.free(data) }
    100 }