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" "image"
"math" "math"
"github.com/hajimehoshi/ebiten/internal/endian"
"github.com/hajimehoshi/ebiten/internal/graphics" "github.com/hajimehoshi/ebiten/internal/graphics"
) )
@ -82,9 +83,9 @@ type textureQuads struct {
height int height int
} }
func (t *textureQuads) vertices() []int16 { func (t *textureQuads) vertices() []uint8 {
l := t.parts.Len() l := t.parts.Len()
vertices := make([]int16, 0, l*16) vertices := make([]uint8, 0, l*32)
p := t.parts p := t.parts
w, h := t.width, t.height w, h := t.width, t.height
width2p := int(graphics.NextPowerOf2Int32(int32(w))) width2p := int(graphics.NextPowerOf2Int32(int32(w)))
@ -100,11 +101,27 @@ func (t *textureQuads) vertices() []int16 {
continue continue
} }
u0, v0, u1, v1 := u(sx0, width2p), v(sy0, height2p), u(sx1, width2p), v(sy1, height2p) u0, v0, u1, v1 := u(sx0, width2p), v(sy0, height2p), u(sx1, width2p), v(sy1, height2p)
if endian.IsLittle() {
vertices = append(vertices, vertices = append(vertices,
x0, y0, u0, v0, uint8(x0), uint8(x0>>8), uint8(y0), uint8(y0>>8),
x1, y0, u1, v0, uint8(u0), uint8(u0>>8), uint8(v0), uint8(v0>>8),
x0, y1, u0, v1, uint8(x1), uint8(x1>>8), uint8(y0), uint8(y0>>8),
x1, y1, u1, v1) 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 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. // glViewport must be called at least at every frame on iOS.
context.ResetViewportSize() context.ResetViewportSize()
for _, g := range q.commandGroups() { for _, g := range q.commandGroups() {
vertices := []int16{} vertices := []uint8{}
for _, c := range g { for _, c := range g {
switch c := c.(type) { switch c := c.(type) {
case *drawImageCommand: case *drawImageCommand:
@ -155,14 +155,14 @@ func (c *fillCommand) Exec(context *opengl.Context, indexOffsetInBytes int) erro
type drawImageCommand struct { type drawImageCommand struct {
dst *Image dst *Image
src *Image src *Image
vertices []int16 vertices []uint8
geo Matrix geo Matrix
color Matrix color Matrix
mode opengl.CompositeMode mode opengl.CompositeMode
} }
const ( 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 { 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 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{ c := &drawImageCommand{
dst: i, dst: i,
src: src, src: src,

View File

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

View File

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

View File

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