buf_js.go (4135B)
1 // Copyright 2019 The Ebiten Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package jsutil 16 17 import ( 18 "syscall/js" 19 ) 20 21 var go2cpp = js.Global().Get("go2cpp").Truthy() 22 23 var ( 24 object = js.Global().Get("Object") 25 arrayBuffer = js.Global().Get("ArrayBuffer") 26 uint8Array = js.Global().Get("Uint8Array") 27 float32Array = js.Global().Get("Float32Array") 28 ) 29 30 var ( 31 // temporaryArrayBuffer is a temporary buffer used at gl.readPixels or gl.texSubImage2D. 32 // The read data is converted to Go's byte slice as soon as possible. 33 // To avoid often allocating ArrayBuffer, reuse the buffer whenever possible. 34 temporaryArrayBuffer = arrayBuffer.New(16) 35 36 // temporaryUint8Array is a Uint8ArrayBuffer whose underlying buffer is always temporaryArrayBuffer. 37 temporaryUint8Array = uint8Array.New(temporaryArrayBuffer) 38 39 // temporaryFloat32Array is a Float32ArrayBuffer whose underlying buffer is always temporaryArrayBuffer. 40 temporaryFloat32Array = float32Array.New(temporaryArrayBuffer) 41 ) 42 43 var ( 44 temporaryArrayBufferByteLengthFunc js.Value 45 temporaryUint8ArrayByteLengthFunc js.Value 46 temporaryFloat32ArrayByteLengthFunc js.Value 47 ) 48 49 func init() { 50 if go2cpp { 51 return 52 } 53 temporaryArrayBufferByteLengthFunc = object.Call("getOwnPropertyDescriptor", arrayBuffer.Get("prototype"), "byteLength").Get("get").Call("bind", temporaryArrayBuffer) 54 temporaryUint8ArrayByteLengthFunc = object.Call("getOwnPropertyDescriptor", object.Call("getPrototypeOf", uint8Array).Get("prototype"), "byteLength").Get("get").Call("bind", temporaryUint8Array) 55 temporaryFloat32ArrayByteLengthFunc = object.Call("getOwnPropertyDescriptor", object.Call("getPrototypeOf", float32Array).Get("prototype"), "byteLength").Get("get").Call("bind", temporaryFloat32Array) 56 } 57 58 func temporaryArrayBufferByteLength() int { 59 if go2cpp { 60 return temporaryArrayBuffer.Get("byteLength").Int() 61 } 62 return temporaryArrayBufferByteLengthFunc.Invoke().Int() 63 } 64 65 func temporaryUint8ArrayByteLength() int { 66 if go2cpp { 67 return temporaryUint8Array.Get("byteLength").Int() 68 } 69 return temporaryUint8ArrayByteLengthFunc.Invoke().Int() 70 } 71 72 func temporaryFloat32ArrayByteLength() int { 73 if go2cpp { 74 return temporaryFloat32Array.Get("byteLength").Int() 75 } 76 return temporaryFloat32ArrayByteLengthFunc.Invoke().Int() 77 } 78 79 func ensureTemporaryArrayBufferSize(byteLength int) { 80 bufl := temporaryArrayBufferByteLength() 81 if bufl < byteLength { 82 for bufl < byteLength { 83 bufl *= 2 84 } 85 temporaryArrayBuffer = arrayBuffer.New(bufl) 86 } 87 if temporaryUint8ArrayByteLength() < bufl { 88 temporaryUint8Array = uint8Array.New(temporaryArrayBuffer) 89 } 90 if temporaryFloat32ArrayByteLength() < bufl { 91 temporaryFloat32Array = float32Array.New(temporaryArrayBuffer) 92 } 93 } 94 95 // TemporaryUint8Array returns a Uint8Array whose length is at least minLength. 96 // Be careful that the length can exceed the given minLength. 97 // data must be a slice of a numeric type for initialization, or nil if you don't need initialization. 98 func TemporaryUint8Array(minLength int, data interface{}) js.Value { 99 ensureTemporaryArrayBufferSize(minLength) 100 if data != nil { 101 copySliceToTemporaryArrayBuffer(data) 102 } 103 return temporaryUint8Array 104 } 105 106 // TemporaryFloat32Array returns a Float32Array whose length is at least minLength. 107 // Be careful that the length can exceed the given minLength. 108 // data must be a slice of a numeric type for initialization, or nil if you don't need initialization. 109 func TemporaryFloat32Array(minLength int, data interface{}) js.Value { 110 ensureTemporaryArrayBufferSize(minLength * 4) 111 if data != nil { 112 copySliceToTemporaryArrayBuffer(data) 113 } 114 return temporaryFloat32Array 115 }