graphics: Bug fix: Command splitting threshold is more strict on browsers?

This commit is contained in:
Hajime Hoshi 2016-10-22 19:16:16 +09:00
parent 27acc5efd9
commit f21f6d357e
10 changed files with 134 additions and 44 deletions

View File

@ -18,6 +18,7 @@ import (
"image"
"math"
"github.com/hajimehoshi/ebiten/internal/endian"
"github.com/hajimehoshi/ebiten/internal/graphics"
)
@ -82,9 +83,9 @@ type textureQuads struct {
height int
}
func (t *textureQuads) vertices() []int16 {
func (t *textureQuads) vertices() []uint8 {
l := t.parts.Len()
vertices := make([]int16, 0, l*16)
vertices := make([]uint8, 0, l*32)
p := t.parts
w, h := t.width, t.height
width2p := int(graphics.NextPowerOf2Int32(int32(w)))
@ -100,11 +101,27 @@ func (t *textureQuads) vertices() []int16 {
continue
}
u0, v0, u1, v1 := u(sx0, width2p), v(sy0, height2p), u(sx1, width2p), v(sy1, height2p)
vertices = append(vertices,
x0, y0, u0, v0,
x1, y0, u1, v0,
x0, y1, u0, v1,
x1, y1, u1, v1)
if endian.IsLittle() {
vertices = append(vertices,
uint8(x0), uint8(x0>>8), uint8(y0), uint8(y0>>8),
uint8(u0), uint8(u0>>8), uint8(v0), uint8(v0>>8),
uint8(x1), uint8(x1>>8), uint8(y0), uint8(y0>>8),
uint8(u1), uint8(u1>>8), uint8(v0), uint8(v0>>8),
uint8(x0), uint8(x0>>8), uint8(y1), uint8(y1>>8),
uint8(u0), uint8(u0>>8), uint8(v1), uint8(v1>>8),
uint8(x1), uint8(x1>>8), uint8(y1), uint8(y1>>8),
uint8(u1), uint8(u1>>8), uint8(v1), uint8(v1>>8))
} else {
vertices = append(vertices,
uint8(x0>>8), uint8(x0), uint8(y0>>8), uint8(y0),
uint8(u0>>8), uint8(u0), uint8(v0>>8), uint8(v0),
uint8(x1>>8), uint8(x1), uint8(y0>>8), uint8(y0),
uint8(u1>>8), uint8(u1), uint8(v0>>8), uint8(v0),
uint8(x0>>8), uint8(x0), uint8(y1>>8), uint8(y1),
uint8(u0>>8), uint8(u0), uint8(v1>>8), uint8(v1),
uint8(x1>>8), uint8(x1), uint8(y1>>8), uint8(y1),
uint8(u1>>8), uint8(u1), uint8(v1>>8), uint8(v1))
}
}
return vertices
}

25
internal/endian/endian.go Normal file
View File

@ -0,0 +1,25 @@
// 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
}

36
internal/endian/js.go Normal file
View File

@ -0,0 +1,36 @@
// 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")
}
}

34
internal/endian/nojs.go Normal file
View File

@ -0,0 +1,34 @@
// 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")
}
}

View File

@ -96,7 +96,7 @@ func (q *commandQueue) Flush(context *opengl.Context) error {
// glViewport must be called at least at every frame on iOS.
context.ResetViewportSize()
for _, g := range q.commandGroups() {
vertices := []int16{}
vertices := []uint8{}
for _, c := range g {
switch c := c.(type) {
case *drawImageCommand:
@ -155,14 +155,14 @@ func (c *fillCommand) Exec(context *opengl.Context, indexOffsetInBytes int) erro
type drawImageCommand struct {
dst *Image
src *Image
vertices []int16
vertices []uint8
geo Matrix
color Matrix
mode opengl.CompositeMode
}
const (
quadVertexNum = 16 // 4 * 2 [vertices] * 2 [tex_coords]
quadVertexNum = 32 // 4 * 2 [vertices] * 2 [tex_coords] * 2[bytes]
)
func (c *drawImageCommand) Exec(context *opengl.Context, indexOffsetInBytes int) error {

View File

@ -94,7 +94,7 @@ func (i *Image) Fill(clr color.RGBA) error {
return nil
}
func (i *Image) DrawImage(src *Image, vertices []int16, geo, clr Matrix, mode opengl.CompositeMode) error {
func (i *Image) DrawImage(src *Image, vertices []uint8, geo, clr Matrix, mode opengl.CompositeMode) error {
c := &drawImageCommand{
dst: i,
src: src,

View File

@ -468,6 +468,7 @@ func (c *Context) NewBuffer(bufferType BufferType, v interface{}, bufferUsage Bu
case int:
gl.BufferData(uint32(bufferType), v, nil, uint32(bufferUsage))
case []uint16:
// TODO: What about the endianness?
gl.BufferData(uint32(bufferType), 2*len(v), gl.Ptr(v), uint32(bufferUsage))
default:
panic("not reach")
@ -485,14 +486,9 @@ func (c *Context) BindElementArrayBuffer(b Buffer) {
})
}
func (c *Context) BufferSubData(bufferType BufferType, data interface{}) {
func (c *Context) BufferSubData(bufferType BufferType, data []uint8) {
_ = c.runOnContextThread(func() error {
switch data := data.(type) {
case []int16:
gl.BufferSubData(uint32(bufferType), 0, 2*len(data), gl.Ptr(data))
default:
panic("not reach")
}
gl.BufferSubData(uint32(bufferType), 0, len(data), gl.Ptr(data))
return nil
})
}

View File

@ -387,14 +387,9 @@ func (c *Context) BindElementArrayBuffer(b Buffer) {
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, b.Object)
}
func (c *Context) BufferSubData(bufferType BufferType, data interface{}) {
func (c *Context) BufferSubData(bufferType BufferType, data []uint8) {
gl := c.gl
switch data := data.(type) {
case []int16:
gl.BufferSubData(int(bufferType), 0, data)
default:
panic("not reach")
}
gl.BufferSubData(int(bufferType), 0, data)
}
func (c *Context) DeleteBuffer(b Buffer) {

View File

@ -357,6 +357,7 @@ func (c *Context) DisableVertexAttribArray(p Program, location string) {
}
func uint16ToBytes(v []uint16) []uint8 {
// TODO: Consider endian?
b := make([]uint8, len(v)*2)
for i, x := range v {
b[2*i] = uint8(x)
@ -365,15 +366,6 @@ func uint16ToBytes(v []uint16) []uint8 {
return b
}
func int16ToBytes(v []int16) []uint8 {
b := make([]uint8, len(v)*2)
for i, x := range v {
b[2*i] = uint8(uint16(x))
b[2*i+1] = uint8(uint16(x) >> 8)
}
return b
}
func (c *Context) NewBuffer(bufferType BufferType, v interface{}, bufferUsage BufferUsage) Buffer {
gl := c.gl
b := gl.CreateBuffer()
@ -394,14 +386,9 @@ func (c *Context) BindElementArrayBuffer(b Buffer) {
gl.BindBuffer(mgl.ELEMENT_ARRAY_BUFFER, mgl.Buffer(b))
}
func (c *Context) BufferSubData(bufferType BufferType, data interface{}) {
func (c *Context) BufferSubData(bufferType BufferType, data []uint8) {
gl := c.gl
switch data := data.(type) {
case []int16:
gl.BufferSubData(mgl.Enum(bufferType), 0, int16ToBytes(data))
default:
panic("not reach")
}
gl.BufferSubData(mgl.Enum(bufferType), 0, data)
}
func (c *Context) DeleteBuffer(b Buffer) {

View File

@ -25,7 +25,7 @@ import (
type drawImageHistoryItem struct {
image *graphics.Image
vertices []int16
vertices []uint8
geom graphics.Matrix
colorm graphics.Matrix
mode opengl.CompositeMode
@ -145,7 +145,7 @@ func (p *Image) ReplacePixels(pixels []uint8) error {
return nil
}
func (p *Image) DrawImage(img *Image, vertices []int16, geom graphics.Matrix, colorm graphics.Matrix, mode opengl.CompositeMode) error {
func (p *Image) DrawImage(img *Image, vertices []uint8, geom graphics.Matrix, colorm graphics.Matrix, mode opengl.CompositeMode) error {
if img.stale || img.volatile {
p.makeStale()
} else {
@ -157,7 +157,7 @@ func (p *Image) DrawImage(img *Image, vertices []int16, geom graphics.Matrix, co
return nil
}
func (p *Image) appendDrawImageHistory(image *graphics.Image, vertices []int16, geom graphics.Matrix, colorm graphics.Matrix, mode opengl.CompositeMode) {
func (p *Image) appendDrawImageHistory(image *graphics.Image, vertices []uint8, geom graphics.Matrix, colorm graphics.Matrix, mode opengl.CompositeMode) {
if p.stale {
return
}