mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +01:00
graphics: Calculate vertices ahead of locking
This commit is contained in:
parent
492f471ec3
commit
b2c5cb164a
29
image.go
29
image.go
@ -88,15 +88,8 @@ func (i *Image) fill(clr color.Color) (err error) {
|
||||
// Be careful that this method is potentially slow.
|
||||
// It would be better if you could call this method fewer times.
|
||||
func (i *Image) DrawImage(image *Image, options *DrawImageOptions) (err error) {
|
||||
imageM.Lock()
|
||||
defer imageM.Unlock()
|
||||
if i.isDisposed() {
|
||||
return errors.New("ebiten: image is already disposed")
|
||||
}
|
||||
if i == image {
|
||||
return errors.New("ebiten: Image.DrawImage: image should be different from the receiver")
|
||||
}
|
||||
i.pixels = nil
|
||||
// Calculate vertices before locking because the user can do anything in
|
||||
// options.ImageParts interface without deadlock (e.g. Call Image functions).
|
||||
if options == nil {
|
||||
options = &DrawImageOptions{}
|
||||
}
|
||||
@ -111,8 +104,24 @@ func (i *Image) DrawImage(image *Image, options *DrawImageOptions) (err error) {
|
||||
}
|
||||
}
|
||||
quads := &textureQuads{parts: parts, width: image.width, height: image.height}
|
||||
// TODO: Reuse one vertices instead of making here, but this would need locking.
|
||||
vertices := make([]int16, 16*graphics.MaxQuads)
|
||||
n := quads.vertices(vertices)
|
||||
if n == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
imageM.Lock()
|
||||
defer imageM.Unlock()
|
||||
if i.isDisposed() {
|
||||
return errors.New("ebiten: image is already disposed")
|
||||
}
|
||||
if i == image {
|
||||
return errors.New("ebiten: Image.DrawImage: image should be different from the receiver")
|
||||
}
|
||||
i.pixels = nil
|
||||
m := opengl.CompositeMode(options.CompositeMode)
|
||||
return i.framebuffer.DrawTexture(glContext, image.texture, quads, &options.GeoM, &options.ColorM, m)
|
||||
return i.framebuffer.DrawTexture(glContext, image.texture, vertices[:16*n], &options.GeoM, &options.ColorM, m)
|
||||
}
|
||||
|
||||
// Bounds returns the bounds of the image.
|
||||
|
@ -88,12 +88,8 @@ type textureQuads struct {
|
||||
height int
|
||||
}
|
||||
|
||||
func (t *textureQuads) Len() int {
|
||||
return t.parts.Len()
|
||||
}
|
||||
|
||||
func (t *textureQuads) SetVertices(vertices []int16) int {
|
||||
l := t.Len()
|
||||
func (t *textureQuads) vertices(vertices []int16) int {
|
||||
l := t.parts.Len()
|
||||
if len(vertices) < l*16 {
|
||||
panic(fmt.Sprintf("graphics: vertices size must be greater than %d but %d", l*16, len(vertices)))
|
||||
}
|
||||
|
@ -33,11 +33,9 @@ type Matrix interface {
|
||||
Element(i, j int) float64
|
||||
}
|
||||
|
||||
var vertices = make([]int16, 16*quadsMaxNum)
|
||||
|
||||
var shadersInitialized = false
|
||||
|
||||
func drawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4][4]float64, quads TextureQuads, geo Matrix, color Matrix, mode opengl.CompositeMode) error {
|
||||
func drawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4][4]float64, vertices []int16, geo Matrix, color Matrix, mode opengl.CompositeMode) error {
|
||||
c.BlendFunc(mode)
|
||||
|
||||
// NOTE: WebGL doesn't seem to have Check gl.MAX_ELEMENTS_VERTICES or gl.MAX_ELEMENTS_INDICES so far.
|
||||
@ -50,12 +48,12 @@ func drawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4
|
||||
shadersInitialized = true
|
||||
}
|
||||
|
||||
l := quads.Len()
|
||||
if l == 0 {
|
||||
n := len(vertices) / 16
|
||||
if n == 0 {
|
||||
return nil
|
||||
}
|
||||
if quadsMaxNum < l {
|
||||
return errors.New(fmt.Sprintf("len(quads) must be equal to or less than %d", quadsMaxNum))
|
||||
if MaxQuads < n/16 {
|
||||
return errors.New(fmt.Sprintf("len(quads) must be equal to or less than %d", MaxQuads))
|
||||
}
|
||||
|
||||
p := programContext{
|
||||
@ -66,10 +64,6 @@ func drawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4
|
||||
geoM: geo,
|
||||
colorM: color,
|
||||
}
|
||||
n := quads.SetVertices(vertices)
|
||||
if n == 0 {
|
||||
return nil
|
||||
}
|
||||
p.begin()
|
||||
defer p.end()
|
||||
c.BufferSubData(c.ArrayBuffer, vertices[:16*n])
|
||||
|
@ -21,11 +21,6 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
|
||||
)
|
||||
|
||||
type TextureQuads interface {
|
||||
Len() int
|
||||
SetVertices(vertices []int16) int
|
||||
}
|
||||
|
||||
func orthoProjectionMatrix(left, right, bottom, top int) *[4][4]float64 {
|
||||
e11 := float64(2) / float64(right-left)
|
||||
e22 := float64(2) / float64(top-bottom)
|
||||
@ -116,12 +111,12 @@ func (f *Framebuffer) Fill(c *opengl.Context, clr color.Color) error {
|
||||
return c.FillFramebuffer(r, g, b, a)
|
||||
}
|
||||
|
||||
func (f *Framebuffer) DrawTexture(c *opengl.Context, t *Texture, quads TextureQuads, geo, clr Matrix, mode opengl.CompositeMode) error {
|
||||
func (f *Framebuffer) DrawTexture(c *opengl.Context, t *Texture, vertices []int16, geo, clr Matrix, mode opengl.CompositeMode) error {
|
||||
if err := f.setAsViewport(c); err != nil {
|
||||
return err
|
||||
}
|
||||
p := f.projectionMatrix()
|
||||
return drawTexture(c, t.native, p, quads, geo, clr, mode)
|
||||
return drawTexture(c, t.native, p, vertices, geo, clr, mode)
|
||||
}
|
||||
|
||||
func (f *Framebuffer) Pixels(c *opengl.Context) ([]uint8, error) {
|
||||
|
@ -16,7 +16,6 @@ package graphics
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
|
||||
"math"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -28,8 +27,8 @@ var (
|
||||
programTexture opengl.Program
|
||||
)
|
||||
|
||||
const indicesNum = math.MaxUint16 + 1
|
||||
const quadsMaxNum = indicesNum / 6
|
||||
const indicesNum = 1 << 16
|
||||
const MaxQuads = indicesNum / 6
|
||||
|
||||
// unsafe.SizeOf can't be used because unsafe doesn't work with GopherJS.
|
||||
const int16Size = 2
|
||||
@ -56,12 +55,12 @@ func initialize(c *opengl.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 16 [bytse] is an arbitrary number which seems enough to draw anything. Fix this if necessary.
|
||||
// 16 [bytes] is an arbitrary number which seems enough to draw anything. Fix this if necessary.
|
||||
const stride = 16
|
||||
c.NewBuffer(c.ArrayBuffer, 4*stride*quadsMaxNum, c.DynamicDraw)
|
||||
c.NewBuffer(c.ArrayBuffer, 4*stride*MaxQuads, c.DynamicDraw)
|
||||
|
||||
indices := make([]uint16, 6*quadsMaxNum)
|
||||
for i := uint16(0); i < quadsMaxNum; i++ {
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user