mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 19:28:57 +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.
|
// Be careful that this method is potentially slow.
|
||||||
// It would be better if you could call this method fewer times.
|
// It would be better if you could call this method fewer times.
|
||||||
func (i *Image) DrawImage(image *Image, options *DrawImageOptions) (err error) {
|
func (i *Image) DrawImage(image *Image, options *DrawImageOptions) (err error) {
|
||||||
imageM.Lock()
|
// Calculate vertices before locking because the user can do anything in
|
||||||
defer imageM.Unlock()
|
// options.ImageParts interface without deadlock (e.g. Call Image functions).
|
||||||
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
|
|
||||||
if options == nil {
|
if options == nil {
|
||||||
options = &DrawImageOptions{}
|
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}
|
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)
|
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.
|
// Bounds returns the bounds of the image.
|
||||||
|
@ -88,12 +88,8 @@ type textureQuads struct {
|
|||||||
height int
|
height int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textureQuads) Len() int {
|
func (t *textureQuads) vertices(vertices []int16) int {
|
||||||
return t.parts.Len()
|
l := t.parts.Len()
|
||||||
}
|
|
||||||
|
|
||||||
func (t *textureQuads) SetVertices(vertices []int16) int {
|
|
||||||
l := t.Len()
|
|
||||||
if len(vertices) < l*16 {
|
if len(vertices) < l*16 {
|
||||||
panic(fmt.Sprintf("graphics: vertices size must be greater than %d but %d", l*16, len(vertices)))
|
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
|
Element(i, j int) float64
|
||||||
}
|
}
|
||||||
|
|
||||||
var vertices = make([]int16, 16*quadsMaxNum)
|
|
||||||
|
|
||||||
var shadersInitialized = false
|
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)
|
c.BlendFunc(mode)
|
||||||
|
|
||||||
// NOTE: WebGL doesn't seem to have Check gl.MAX_ELEMENTS_VERTICES or gl.MAX_ELEMENTS_INDICES so far.
|
// 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
|
shadersInitialized = true
|
||||||
}
|
}
|
||||||
|
|
||||||
l := quads.Len()
|
n := len(vertices) / 16
|
||||||
if l == 0 {
|
if n == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if quadsMaxNum < l {
|
if MaxQuads < n/16 {
|
||||||
return errors.New(fmt.Sprintf("len(quads) must be equal to or less than %d", quadsMaxNum))
|
return errors.New(fmt.Sprintf("len(quads) must be equal to or less than %d", MaxQuads))
|
||||||
}
|
}
|
||||||
|
|
||||||
p := programContext{
|
p := programContext{
|
||||||
@ -66,10 +64,6 @@ func drawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4
|
|||||||
geoM: geo,
|
geoM: geo,
|
||||||
colorM: color,
|
colorM: color,
|
||||||
}
|
}
|
||||||
n := quads.SetVertices(vertices)
|
|
||||||
if n == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
p.begin()
|
p.begin()
|
||||||
defer p.end()
|
defer p.end()
|
||||||
c.BufferSubData(c.ArrayBuffer, vertices[:16*n])
|
c.BufferSubData(c.ArrayBuffer, vertices[:16*n])
|
||||||
|
@ -21,11 +21,6 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
|
"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 {
|
func orthoProjectionMatrix(left, right, bottom, top int) *[4][4]float64 {
|
||||||
e11 := float64(2) / float64(right-left)
|
e11 := float64(2) / float64(right-left)
|
||||||
e22 := float64(2) / float64(top-bottom)
|
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)
|
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 {
|
if err := f.setAsViewport(c); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p := f.projectionMatrix()
|
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) {
|
func (f *Framebuffer) Pixels(c *opengl.Context) ([]uint8, error) {
|
||||||
|
@ -16,7 +16,6 @@ package graphics
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
|
"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
|
||||||
"math"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -28,8 +27,8 @@ var (
|
|||||||
programTexture opengl.Program
|
programTexture opengl.Program
|
||||||
)
|
)
|
||||||
|
|
||||||
const indicesNum = math.MaxUint16 + 1
|
const indicesNum = 1 << 16
|
||||||
const quadsMaxNum = indicesNum / 6
|
const MaxQuads = indicesNum / 6
|
||||||
|
|
||||||
// unsafe.SizeOf can't be used because unsafe doesn't work with GopherJS.
|
// unsafe.SizeOf can't be used because unsafe doesn't work with GopherJS.
|
||||||
const int16Size = 2
|
const int16Size = 2
|
||||||
@ -56,12 +55,12 @@ func initialize(c *opengl.Context) error {
|
|||||||
return err
|
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
|
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)
|
indices := make([]uint16, 6*MaxQuads)
|
||||||
for i := uint16(0); i < quadsMaxNum; i++ {
|
for i := uint16(0); i < MaxQuads; i++ {
|
||||||
indices[6*i+0] = 4*i + 0
|
indices[6*i+0] = 4*i + 0
|
||||||
indices[6*i+1] = 4*i + 1
|
indices[6*i+1] = 4*i + 1
|
||||||
indices[6*i+2] = 4*i + 2
|
indices[6*i+2] = 4*i + 2
|
||||||
|
Loading…
Reference in New Issue
Block a user