diff --git a/internal/graphicsdriver/opengl/context_js.go b/internal/graphicsdriver/opengl/context_js.go index 6329db9f6..ce44ff9eb 100644 --- a/internal/graphicsdriver/opengl/context_js.go +++ b/internal/graphicsdriver/opengl/context_js.go @@ -242,7 +242,7 @@ func (c *context) framebufferPixels(f *framebuffer, width, height int) []byte { c.bindFramebuffer(f.native) l := 4 * width * height - p := jsutil.TemporaryUint8Array(l, nil) + p := jsutil.TemporaryUint8ArrayFromUint8Slice(l, nil) gl.readPixels.Invoke(0, 0, width, height, gles.RGBA, gles.UNSIGNED_BYTE, p) return uint8ArrayToSlice(p, l) @@ -567,7 +567,7 @@ func (c *context) bindElementArrayBuffer(b buffer) { func (c *context) arrayBufferSubData(data []float32) { gl := c.gl l := len(data) * 4 - arr := jsutil.TemporaryUint8Array(l, data) + arr := jsutil.TemporaryUint8ArrayFromFloat32Slice(l, data) if c.usesWebGL2() { gl.bufferSubData.Invoke(gles.ARRAY_BUFFER, 0, arr, 0, l) } else { @@ -578,7 +578,7 @@ func (c *context) arrayBufferSubData(data []float32) { func (c *context) elementArrayBufferSubData(data []uint16) { gl := c.gl l := len(data) * 2 - arr := jsutil.TemporaryUint8Array(l, data) + arr := jsutil.TemporaryUint8ArrayFromUint16Slice(l, data) if c.usesWebGL2() { gl.bufferSubData.Invoke(gles.ELEMENT_ARRAY_BUFFER, 0, arr, 0, l) } else { @@ -624,7 +624,7 @@ func (c *context) texSubImage2D(t textureNative, args []*driver.ReplacePixelsArg c.bindTexture(t) gl := c.gl for _, a := range args { - arr := jsutil.TemporaryUint8Array(len(a.Pixels), a.Pixels) + arr := jsutil.TemporaryUint8ArrayFromUint8Slice(len(a.Pixels), a.Pixels) if c.usesWebGL2() { // void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, // GLsizei width, GLsizei height, diff --git a/internal/jsutil/buf_js.go b/internal/jsutil/buf_js.go index 990836063..640c917ed 100644 --- a/internal/jsutil/buf_js.go +++ b/internal/jsutil/buf_js.go @@ -92,24 +92,38 @@ func ensureTemporaryArrayBufferSize(byteLength int) { } } -// TemporaryUint8Array returns a Uint8Array whose length is at least minLength. +// TemporaryUint8ArrayFromUint8Slice returns a Uint8Array whose length is at least minLength from a uint8 slice. // Be careful that the length can exceed the given minLength. // data must be a slice of a numeric type for initialization, or nil if you don't need initialization. -func TemporaryUint8Array(minLength int, data interface{}) js.Value { +func TemporaryUint8ArrayFromUint8Slice(minLength int, data []uint8) js.Value { ensureTemporaryArrayBufferSize(minLength) - if data != nil { - copySliceToTemporaryArrayBuffer(data) - } + copyUint8SliceToTemporaryArrayBuffer(data) + return temporaryUint8Array +} + +// TemporaryUint8ArrayFromUint16Slice returns a Uint8Array whose length is at least minLength from a uint16 slice. +// Be careful that the length can exceed the given minLength. +// data must be a slice of a numeric type for initialization, or nil if you don't need initialization. +func TemporaryUint8ArrayFromUint16Slice(minLength int, data []uint16) js.Value { + ensureTemporaryArrayBufferSize(minLength * 2) + copyUint16SliceToTemporaryArrayBuffer(data) + return temporaryUint8Array +} + +// TemporaryUint8ArrayFromFloat32Slice returns a Uint8Array whose length is at least minLength from a float32 slice. +// Be careful that the length can exceed the given minLength. +// data must be a slice of a numeric type for initialization, or nil if you don't need initialization. +func TemporaryUint8ArrayFromFloat32Slice(minLength int, data []float32) js.Value { + ensureTemporaryArrayBufferSize(minLength * 4) + copyFloat32SliceToTemporaryArrayBuffer(data) return temporaryUint8Array } // TemporaryFloat32Array returns a Float32Array whose length is at least minLength. // Be careful that the length can exceed the given minLength. // data must be a slice of a numeric type for initialization, or nil if you don't need initialization. -func TemporaryFloat32Array(minLength int, data interface{}) js.Value { +func TemporaryFloat32Array(minLength int, data []float32) js.Value { ensureTemporaryArrayBufferSize(minLength * 4) - if data != nil { - copySliceToTemporaryArrayBuffer(data) - } + copyFloat32SliceToTemporaryArrayBuffer(data) return temporaryFloat32Array } diff --git a/internal/jsutil/slice_js.go b/internal/jsutil/slice_js.go index 496b7e8b7..ebcb745b3 100644 --- a/internal/jsutil/slice_js.go +++ b/internal/jsutil/slice_js.go @@ -15,82 +15,39 @@ package jsutil import ( - "fmt" "reflect" "runtime" "syscall/js" "unsafe" ) -func sliceToByteSlice(s interface{}) (bs []byte) { - switch s := s.(type) { - case []int8: - h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) - bs = *(*[]byte)(unsafe.Pointer(h)) - runtime.KeepAlive(s) - case []int16: - h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) - h.Len *= 2 - h.Cap *= 2 - bs = *(*[]byte)(unsafe.Pointer(h)) - runtime.KeepAlive(s) - case []int32: - h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) - h.Len *= 4 - h.Cap *= 4 - bs = *(*[]byte)(unsafe.Pointer(h)) - runtime.KeepAlive(s) - case []int64: - h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) - h.Len *= 8 - h.Cap *= 8 - bs = *(*[]byte)(unsafe.Pointer(h)) - runtime.KeepAlive(s) - case []uint8: - return s - case []uint16: - h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) - h.Len *= 2 - h.Cap *= 2 - bs = *(*[]byte)(unsafe.Pointer(h)) - runtime.KeepAlive(s) - case []uint32: - h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) - h.Len *= 4 - h.Cap *= 4 - bs = *(*[]byte)(unsafe.Pointer(h)) - runtime.KeepAlive(s) - case []uint64: - h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) - h.Len *= 8 - h.Cap *= 8 - bs = *(*[]byte)(unsafe.Pointer(h)) - runtime.KeepAlive(s) - case []float32: - h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) - h.Len *= 4 - h.Cap *= 4 - bs = *(*[]byte)(unsafe.Pointer(h)) - runtime.KeepAlive(s) - case []float64: - h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) - h.Len *= 8 - h.Cap *= 8 - bs = *(*[]byte)(unsafe.Pointer(h)) - runtime.KeepAlive(s) - default: - panic(fmt.Sprintf("jsutil: unexpected value at sliceToBytesSlice: %T", s)) +func copyUint8SliceToTemporaryArrayBuffer(src []uint8) { + if len(src) == 0 { + return } - return + js.CopyBytesToJS(temporaryUint8Array, src) } -func copySliceToTemporaryArrayBuffer(src interface{}) { - switch s := src.(type) { - case []uint8: - js.CopyBytesToJS(temporaryUint8Array, s) - case []int8, []int16, []int32, []uint16, []uint32, []float32, []float64: - js.CopyBytesToJS(temporaryUint8Array, sliceToByteSlice(s)) - default: - panic(fmt.Sprintf("jsutil: unexpected value at CopySliceToJS: %T", s)) +func copyUint16SliceToTemporaryArrayBuffer(src []uint16) { + if len(src) == 0 { + return } + h := (*reflect.SliceHeader)(unsafe.Pointer(&src)) + h.Len *= 2 + h.Cap *= 2 + bs := *(*[]byte)(unsafe.Pointer(h)) + runtime.KeepAlive(src) + js.CopyBytesToJS(temporaryUint8Array, bs) +} + +func copyFloat32SliceToTemporaryArrayBuffer(src []float32) { + if len(src) == 0 { + return + } + h := (*reflect.SliceHeader)(unsafe.Pointer(&src)) + h.Len *= 4 + h.Cap *= 4 + bs := *(*[]byte)(unsafe.Pointer(h)) + runtime.KeepAlive(src) + js.CopyBytesToJS(temporaryUint8Array, bs) }