From 3479b80f1ceb8a1c0120e71d7a1fd166396ea53a Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sun, 4 Mar 2018 17:57:50 +0900 Subject: [PATCH] opengl: Use unsafe-way to convert []float32/[]uint16 to []byte; Remove internal/endian --- internal/endian/endian.go | 25 ------------------ internal/endian/js.go | 36 -------------------------- internal/endian/nojs.go | 34 ------------------------ internal/graphics/command.go | 3 +++ internal/graphics/program.go | 21 +++++++++------ internal/opengl/context_mobile.go | 43 ++++++++++++------------------- 6 files changed, 32 insertions(+), 130 deletions(-) delete mode 100644 internal/endian/endian.go delete mode 100644 internal/endian/js.go delete mode 100644 internal/endian/nojs.go diff --git a/internal/endian/endian.go b/internal/endian/endian.go deleted file mode 100644 index 3bf9c037a..000000000 --- a/internal/endian/endian.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2016 The Ebiten Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package endian - -var isLittleEndian = false - -func IsLittle() bool { - return isLittleEndian -} - -func IsBig() bool { - return !isLittleEndian -} diff --git a/internal/endian/js.go b/internal/endian/js.go deleted file mode 100644 index 6695ab621..000000000 --- a/internal/endian/js.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2016 The Ebiten Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build js - -package endian - -import ( - "github.com/gopherjs/gopherjs/js" -) - -func init() { - a := js.Global.Get("ArrayBuffer").New(4) - a8 := js.Global.Get("Uint8Array").New(a) - a32 := js.Global.Get("Uint32Array").New(a) - a32.SetIndex(0, 1) - switch a8.Index(0).Int() { - case 1: - isLittleEndian = true - case 0: - isLittleEndian = false - default: - panic("not reach") - } -} diff --git a/internal/endian/nojs.go b/internal/endian/nojs.go deleted file mode 100644 index 985fe9564..000000000 --- a/internal/endian/nojs.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 The Ebiten Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build !js - -package endian - -import ( - "unsafe" -) - -func init() { - i := int(1) - b := (*uint8)(unsafe.Pointer(&i)) - switch *b { - case 1: - isLittleEndian = true - case 0: - isLittleEndian = false - default: - panic("not reach") - } -} diff --git a/internal/graphics/command.go b/internal/graphics/command.go index 50875144e..cb655b7e8 100644 --- a/internal/graphics/command.go +++ b/internal/graphics/command.go @@ -149,6 +149,9 @@ func (q *commandQueue) Flush() error { } } if 0 < n-lastN { + // Note that the vertices passed to BufferSubData is not under GC management + // in opengl package due to unsafe-way. + // See BufferSubData in context_mobile.go. opengl.GetContext().BufferSubData(opengl.ArrayBuffer, q.vertices[lastN:n]) } // NOTE: WebGL doesn't seem to have Check gl.MAX_ELEMENTS_VERTICES or gl.MAX_ELEMENTS_INDICES so far. diff --git a/internal/graphics/program.go b/internal/graphics/program.go index d5a750c0f..a3f272bb3 100644 --- a/internal/graphics/program.go +++ b/internal/graphics/program.go @@ -120,6 +120,8 @@ type openGLState struct { lastColorMatrixTranslation []float32 lastSourceWidth int lastSourceHeight int + + indices []uint16 } var ( @@ -226,16 +228,19 @@ func (s *openGLState) reset() error { s.arrayBuffer = theArrayBufferLayout.newArrayBuffer() - indices := make([]uint16, 6*maxQuads) + s.indices = make([]uint16, 6*maxQuads) for i := uint16(0); i < maxQuads; i++ { - indices[6*i+0] = 4*i + 0 - indices[6*i+1] = 4*i + 1 - indices[6*i+2] = 4*i + 2 - indices[6*i+3] = 4*i + 1 - indices[6*i+4] = 4*i + 2 - indices[6*i+5] = 4*i + 3 + s.indices[6*i+0] = 4*i + 0 + s.indices[6*i+1] = 4*i + 1 + s.indices[6*i+2] = 4*i + 2 + s.indices[6*i+3] = 4*i + 1 + s.indices[6*i+4] = 4*i + 2 + s.indices[6*i+5] = 4*i + 3 } - s.elementArrayBuffer = opengl.GetContext().NewElementArrayBuffer(indices) + // Note that the indices passed to NewElementArrayBuffer is not under GC management + // in opengl package due to unsafe-way. + // See NewElementArrayBuffer in context_mobile.go. + s.elementArrayBuffer = opengl.GetContext().NewElementArrayBuffer(s.indices) return nil } diff --git a/internal/opengl/context_mobile.go b/internal/opengl/context_mobile.go index fed1e8705..5661abff4 100644 --- a/internal/opengl/context_mobile.go +++ b/internal/opengl/context_mobile.go @@ -19,9 +19,9 @@ package opengl import ( "errors" "fmt" - "math" + "reflect" + "unsafe" - "github.com/hajimehoshi/ebiten/internal/endian" mgl "golang.org/x/mobile/gl" ) @@ -352,12 +352,13 @@ func (c *Context) DisableVertexAttribArray(p Program, location string) { } func uint16ToBytes(v []uint16) []byte { - // TODO: Consider endian? - b := make([]byte, len(v)*2) - for i, x := range v { - b[2*i] = uint8(x) - b[2*i+1] = uint8(x >> 8) - } + u16h := (*reflect.SliceHeader)(unsafe.Pointer(&v)) + + var b []byte + bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + bh.Data = u16h.Data + bh.Len = len(v) * 2 + bh.Cap = len(v) * 2 return b } @@ -383,25 +384,13 @@ func (c *Context) BindElementArrayBuffer(b Buffer) { } func float32ToBytes(v []float32) []byte { - b := make([]byte, len(v)*4) - if endian.IsLittle() { - for i, x := range v { - bits := math.Float32bits(x) - b[4*i] = uint8(bits) - b[4*i+1] = uint8(bits >> 8) - b[4*i+2] = uint8(bits >> 16) - b[4*i+3] = uint8(bits >> 24) - } - } else { - // TODO: Test this - for i, x := range v { - bits := math.Float32bits(x) - b[4*i] = uint8(bits >> 24) - b[4*i+1] = uint8(bits >> 16) - b[4*i+2] = uint8(bits >> 8) - b[4*i+3] = uint8(bits) - } - } + f32h := (*reflect.SliceHeader)(unsafe.Pointer(&v)) + + var b []byte + bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + bh.Data = f32h.Data + bh.Len = len(v) * 4 + bh.Cap = len(v) * 4 return b }