diff --git a/.github/workflows/govetblock.txt b/.github/workflows/govetblock.txt index 72bc6ae49..0b9f018c6 100644 --- a/.github/workflows/govetblock.txt +++ b/.github/workflows/govetblock.txt @@ -1,2 +1,4 @@ +github.com/hajimehoshi/ebiten/v2/internal/cocoa github.com/hajimehoshi/ebiten/v2/internal/glfwwin github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/directx +github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal/mtl diff --git a/internal/cocoa/api_cocoa_darwin.go b/internal/cocoa/api_cocoa_darwin.go index 4f414ec12..880072e86 100644 --- a/internal/cocoa/api_cocoa_darwin.go +++ b/internal/cocoa/api_cocoa_darwin.go @@ -15,7 +15,6 @@ package cocoa import ( - "reflect" "unsafe" "github.com/ebitengine/purego/objc" @@ -277,15 +276,13 @@ func (s NSString) InitWithUTF8String(utf8 string) NSString { } func (s NSString) String() string { - // this will be nicer with unsafe.Slice once ebitengine requires 1.17 - // reflect.SliceHeader is used because it will force Go to copy the string - // into Go memory when casted to a string - var b []byte - header := (*reflect.SliceHeader)(unsafe.Pointer(&b)) - header.Data = uintptr(s.Send(sel_UTF8String)) - header.Len = int(s.Send(sel_length)) - header.Cap = header.Len - return string(b) + // The lifetime of the underlying C string is shorter than s [1]. + // Copy the bytes to ensure that the returned string's lifetime is unrelated to s. + // [1] https://developer.apple.com/documentation/foundation/nsstring/1411189-utf8string?language=objc + src := unsafe.Slice((*byte)(unsafe.Pointer(s.Send(sel_UTF8String))), s.Send(sel_length)) + dst := make([]byte, len(src)) + copy(dst, src) + return string(dst) } type NSNotification struct { diff --git a/internal/glfwwin/win32window_windows.go b/internal/glfwwin/win32window_windows.go index 05c8052ce..9035b49bc 100644 --- a/internal/glfwwin/win32window_windows.go +++ b/internal/glfwwin/win32window_windows.go @@ -9,7 +9,6 @@ import ( "errors" "fmt" "math" - "reflect" "runtime" "unsafe" @@ -100,11 +99,7 @@ func createIcon(image *Image, xhot, yhot int, icon bool) (_HICON, error) { }() source := image.Pixels - var target []byte - h := (*reflect.SliceHeader)(unsafe.Pointer(&target)) - h.Data = uintptr(unsafe.Pointer(targetPtr)) - h.Len = len(source) - h.Cap = len(source) + target := unsafe.Slice((*byte)(unsafe.Pointer(targetPtr)), len(source)) for i := 0; i < len(source)/4; i++ { target[4*i] = source[4*i+2] target[4*i+1] = source[4*i+1] diff --git a/internal/graphicsdriver/directx/graphics_windows.go b/internal/graphicsdriver/directx/graphics_windows.go index 4a6d73c90..0c3b0d20e 100644 --- a/internal/graphicsdriver/directx/graphics_windows.go +++ b/internal/graphicsdriver/directx/graphics_windows.go @@ -18,7 +18,6 @@ import ( "errors" "fmt" "os" - "reflect" "strings" "time" "unsafe" @@ -1013,14 +1012,14 @@ func (g *Graphics) SetVertices(vertices []float32, indices []uint16) (ferr error if err != nil { return err } - copyFloat32s(m, vertices) + copy(unsafe.Slice((*float32)(unsafe.Pointer(m)), len(vertices)), vertices) g.vertices[g.frameIndex][vidx].Unmap(0, nil) m, err = g.indices[g.frameIndex][iidx].Map(0, &_D3D12_RANGE{0, 0}) if err != nil { return err } - copyUint16s(m, indices) + copy(unsafe.Slice((*uint16)(unsafe.Pointer(m)), len(indices)), indices) g.indices[g.frameIndex][iidx].Unmap(0, nil) return nil @@ -1471,12 +1470,7 @@ func (i *Image) ReadPixels(buf []byte, x, y, width, height int) error { return err } - var dstBytes []byte - h := (*reflect.SliceHeader)(unsafe.Pointer(&dstBytes)) - h.Data = uintptr(m) - h.Len = int(i.totalBytes) - h.Cap = int(i.totalBytes) - + dstBytes := unsafe.Slice((*byte)(unsafe.Pointer(m)), i.totalBytes) for j := 0; j < height; j++ { copy(buf[j*width*4:(j+1)*width*4], dstBytes[j*int(i.layouts.Footprint.RowPitch):]) } @@ -1510,11 +1504,7 @@ func (i *Image) WritePixels(args []*graphicsdriver.WritePixelsArgs) error { i.graphics.needFlushCopyCommandList = true - var srcBytes []byte - h := (*reflect.SliceHeader)(unsafe.Pointer(&srcBytes)) - h.Data = uintptr(m) - h.Len = int(i.totalBytes) - h.Cap = int(i.totalBytes) + srcBytes := unsafe.Slice((*byte)(unsafe.Pointer(m)), i.totalBytes) for _, a := range args { for j := 0; j < a.Height; j++ { copy(srcBytes[(a.Y+j)*int(i.layouts.Footprint.RowPitch)+a.X*4:], a.Pixels[j*a.Width*4:(j+1)*a.Width*4]) @@ -1725,24 +1715,6 @@ func (i *Image) ensureDepthStencilView(device *_ID3D12Device) error { return nil } -func copyFloat32s(dst uintptr, src []float32) { - var dsts []float32 - h := (*reflect.SliceHeader)(unsafe.Pointer(&dsts)) - h.Data = dst - h.Len = len(src) - h.Cap = len(src) - copy(dsts, src) -} - -func copyUint16s(dst uintptr, src []uint16) { - var dsts []uint16 - h := (*reflect.SliceHeader)(unsafe.Pointer(&dsts)) - h.Data = dst - h.Len = len(src) - h.Cap = len(src) - copy(dsts, src) -} - type stencilMode int const ( diff --git a/internal/graphicsdriver/directx/pipeline_windows.go b/internal/graphicsdriver/directx/pipeline_windows.go index d5fa1655c..28c882dd6 100644 --- a/internal/graphicsdriver/directx/pipeline_windows.go +++ b/internal/graphicsdriver/directx/pipeline_windows.go @@ -228,7 +228,7 @@ func (p *pipelineStates) useGraphicsPipelineState(device *_ID3D12Device, command } // Update the constant buffer. - copyFloat32s(m, uniforms) + copy(unsafe.Slice((*float32)(unsafe.Pointer(m)), len(uniforms)), uniforms) commandList.SetPipelineState(pipelineState) diff --git a/internal/graphicsdriver/metal/mtl/mtl_darwin.go b/internal/graphicsdriver/metal/mtl/mtl_darwin.go index 99bddbd0b..7c8cb1325 100644 --- a/internal/graphicsdriver/metal/mtl/mtl_darwin.go +++ b/internal/graphicsdriver/metal/mtl/mtl_darwin.go @@ -25,7 +25,6 @@ package mtl import ( "errors" "fmt" - "reflect" "runtime" "unsafe" @@ -1086,18 +1085,7 @@ func (b Buffer) Length() uintptr { func (b Buffer) CopyToContents(data unsafe.Pointer, lengthInBytes uintptr) { contents := b.buffer.Send(sel_contents) - // use unsafe.Slice when ebitengine reaches 1.17 - var contentSlice []byte - contentHeader := (*reflect.SliceHeader)(unsafe.Pointer(&contentSlice)) - contentHeader.Data = uintptr(contents) - contentHeader.Len = int(lengthInBytes) - contentHeader.Cap = int(lengthInBytes) - var dataSlice []byte - dataHeader := (*reflect.SliceHeader)(unsafe.Pointer(&dataSlice)) - dataHeader.Data = uintptr(data) - dataHeader.Len = int(lengthInBytes) - dataHeader.Cap = int(lengthInBytes) - copy(contentSlice, dataSlice) + copy(unsafe.Slice((*byte)(unsafe.Pointer(contents)), lengthInBytes), unsafe.Slice((*byte)(data), lengthInBytes)) if runtime.GOOS != "ios" { b.buffer.Send(sel_didModifyRange, 0, lengthInBytes) } diff --git a/internal/graphicsdriver/opengl/bytes.go b/internal/graphicsdriver/opengl/bytes.go deleted file mode 100644 index 88105a9c4..000000000 --- a/internal/graphicsdriver/opengl/bytes.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2018 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 opengl - -import ( - "reflect" - "unsafe" -) - -func float32sToBytes(v []float32) []byte { - 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 -} - -func uint16sToBytes(v []uint16) []byte { - 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 -} diff --git a/internal/graphicsdriver/opengl/context_gles.go b/internal/graphicsdriver/opengl/context_gles.go index 8e9245121..a84163531 100644 --- a/internal/graphicsdriver/opengl/context_gles.go +++ b/internal/graphicsdriver/opengl/context_gles.go @@ -21,6 +21,7 @@ package opengl import ( "errors" "fmt" + "unsafe" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl/glconst" @@ -421,11 +422,13 @@ func (c *context) bindElementArrayBuffer(b buffer) { } func (c *context) arrayBufferSubData(data []float32) { - c.ctx.BufferSubData(glconst.ARRAY_BUFFER, 0, float32sToBytes(data)) + s := unsafe.Slice((*byte)(unsafe.Pointer(&data[0])), len(data)*4) + c.ctx.BufferSubData(glconst.ARRAY_BUFFER, 0, s) } func (c *context) elementArrayBufferSubData(data []uint16) { - c.ctx.BufferSubData(glconst.ELEMENT_ARRAY_BUFFER, 0, uint16sToBytes(data)) + s := unsafe.Slice((*byte)(unsafe.Pointer(&data[0])), len(data)*2) + c.ctx.BufferSubData(glconst.ELEMENT_ARRAY_BUFFER, 0, s) } func (c *context) deleteBuffer(b buffer) { diff --git a/internal/jsutil/slice_js.go b/internal/jsutil/slice_js.go index ebcb745b3..f120a2669 100644 --- a/internal/jsutil/slice_js.go +++ b/internal/jsutil/slice_js.go @@ -15,7 +15,6 @@ package jsutil import ( - "reflect" "runtime" "syscall/js" "unsafe" @@ -32,22 +31,14 @@ 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)) + js.CopyBytesToJS(temporaryUint8Array, unsafe.Slice((*byte)(unsafe.Pointer(&src[0])), len(src)*2)) 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)) + js.CopyBytesToJS(temporaryUint8Array, unsafe.Slice((*byte)(unsafe.Pointer(&src[0])), len(src)*4)) runtime.KeepAlive(src) - js.CopyBytesToJS(temporaryUint8Array, bs) }