mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 03:38:55 +01:00
graphics: Split the notion of vertices and elements
This commit is contained in:
parent
a54b6060bd
commit
525ad04568
@ -31,7 +31,9 @@ import (
|
|||||||
type command interface {
|
type command interface {
|
||||||
Exec(indexOffsetInBytes int) error
|
Exec(indexOffsetInBytes int) error
|
||||||
NumVertices() int
|
NumVertices() int
|
||||||
|
NumElements() int
|
||||||
AddNumVertices(n int)
|
AddNumVertices(n int)
|
||||||
|
AddNumElements(n int)
|
||||||
CanMerge(dst, src *Image, color *affine.ColorM, mode opengl.CompositeMode, filter Filter) bool
|
CanMerge(dst, src *Image, color *affine.ColorM, mode opengl.CompositeMode, filter Filter) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +50,7 @@ type commandQueue struct {
|
|||||||
// vertices is never shrunk since re-extending a vertices buffer is heavy.
|
// vertices is never shrunk since re-extending a vertices buffer is heavy.
|
||||||
nvertices int
|
nvertices int
|
||||||
|
|
||||||
indices []uint16
|
elements []uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
// theCommandQueue is the command queue for the current process.
|
// theCommandQueue is the command queue for the current process.
|
||||||
@ -56,15 +58,15 @@ var theCommandQueue = &commandQueue{}
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
q := theCommandQueue
|
q := theCommandQueue
|
||||||
// Initialize indices for drawImageCommand.
|
// Initialize elements for drawImageCommand.
|
||||||
q.indices = make([]uint16, 6*maxQuads)
|
q.elements = make([]uint16, 6*maxQuads)
|
||||||
for i := uint16(0); i < maxQuads; i++ {
|
for i := uint16(0); i < maxQuads; i++ {
|
||||||
q.indices[6*i+0] = 4*i + 0
|
q.elements[6*i+0] = 4*i + 0
|
||||||
q.indices[6*i+1] = 4*i + 1
|
q.elements[6*i+1] = 4*i + 1
|
||||||
q.indices[6*i+2] = 4*i + 2
|
q.elements[6*i+2] = 4*i + 2
|
||||||
q.indices[6*i+3] = 4*i + 1
|
q.elements[6*i+3] = 4*i + 1
|
||||||
q.indices[6*i+4] = 4*i + 2
|
q.elements[6*i+4] = 4*i + 2
|
||||||
q.indices[6*i+5] = 4*i + 3
|
q.elements[6*i+5] = 4*i + 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,10 +88,12 @@ func (q *commandQueue) appendVertices(vertices []float32) {
|
|||||||
func (q *commandQueue) EnqueueDrawImageCommand(dst, src *Image, vertices []float32, color *affine.ColorM, mode opengl.CompositeMode, filter Filter) {
|
func (q *commandQueue) EnqueueDrawImageCommand(dst, src *Image, vertices []float32, color *affine.ColorM, mode opengl.CompositeMode, filter Filter) {
|
||||||
// Avoid defer for performance
|
// Avoid defer for performance
|
||||||
q.appendVertices(vertices)
|
q.appendVertices(vertices)
|
||||||
|
ne := 6 * len(vertices) * opengl.Float.SizeInBytes() / QuadVertexSizeInBytes()
|
||||||
if 0 < len(q.commands) {
|
if 0 < len(q.commands) {
|
||||||
last := q.commands[len(q.commands)-1]
|
last := q.commands[len(q.commands)-1]
|
||||||
if last.CanMerge(dst, src, color, mode, filter) {
|
if last.CanMerge(dst, src, color, mode, filter) {
|
||||||
last.AddNumVertices(len(vertices))
|
last.AddNumVertices(len(vertices))
|
||||||
|
last.AddNumElements(ne)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,6 +101,7 @@ func (q *commandQueue) EnqueueDrawImageCommand(dst, src *Image, vertices []float
|
|||||||
dst: dst,
|
dst: dst,
|
||||||
src: src,
|
src: src,
|
||||||
nvertices: len(vertices),
|
nvertices: len(vertices),
|
||||||
|
nelements: ne,
|
||||||
color: color,
|
color: color,
|
||||||
mode: mode,
|
mode: mode,
|
||||||
filter: filter,
|
filter: filter,
|
||||||
@ -125,6 +130,9 @@ func (q *commandQueue) commandGroups() [][]command {
|
|||||||
c := cs[0]
|
c := cs[0]
|
||||||
switch c := c.(type) {
|
switch c := c.(type) {
|
||||||
case *drawImageCommand:
|
case *drawImageCommand:
|
||||||
|
// NOTE: WebGL doesn't seem to have gl.MAX_ELEMENTS_VERTICES or
|
||||||
|
// gl.MAX_ELEMENTS_INDICES so far.
|
||||||
|
// Let's use them to compare to len(quads) in the future.
|
||||||
if maxQuads >= quads+c.quadsNum() {
|
if maxQuads >= quads+c.quadsNum() {
|
||||||
quads += c.quadsNum()
|
quads += c.quadsNum()
|
||||||
break
|
break
|
||||||
@ -156,26 +164,19 @@ func (q *commandQueue) Flush() error {
|
|||||||
// Note that the vertices passed to BufferSubData is not under GC management
|
// Note that the vertices passed to BufferSubData is not under GC management
|
||||||
// in opengl package due to unsafe-way.
|
// in opengl package due to unsafe-way.
|
||||||
// See BufferSubData in context_mobile.go.
|
// See BufferSubData in context_mobile.go.
|
||||||
opengl.GetContext().ElementArrayBufferSubData(q.indices)
|
opengl.GetContext().ElementArrayBufferSubData(q.elements)
|
||||||
opengl.GetContext().ArrayBufferSubData(q.vertices[lastN:n])
|
opengl.GetContext().ArrayBufferSubData(q.vertices[lastN:n])
|
||||||
}
|
}
|
||||||
// NOTE: WebGL doesn't seem to have gl.MAX_ELEMENTS_VERTICES or
|
|
||||||
// gl.MAX_ELEMENTS_INDICES so far.
|
|
||||||
// Let's use them to compare to len(quads) in the future.
|
|
||||||
if maxQuads < (n-lastN)*opengl.Float.SizeInBytes()/QuadVertexSizeInBytes() {
|
|
||||||
return fmt.Errorf("len(quads) must be equal to or less than %d", maxQuads)
|
|
||||||
}
|
|
||||||
numc := len(g)
|
numc := len(g)
|
||||||
indexOffsetInBytes := 0
|
indexOffsetInBytes := 0
|
||||||
for _, c := range g {
|
for _, c := range g {
|
||||||
if err := c.Exec(indexOffsetInBytes); err != nil {
|
if err := c.Exec(indexOffsetInBytes); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
n := c.NumVertices() * opengl.Float.SizeInBytes() / QuadVertexSizeInBytes()
|
|
||||||
// TODO: indexOffsetInBytes should be reset if the command type is different
|
// TODO: indexOffsetInBytes should be reset if the command type is different
|
||||||
// from the previous one. This fix is needed when another drawing command is
|
// from the previous one. This fix is needed when another drawing command is
|
||||||
// introduced than drawImageCommand.
|
// introduced than drawImageCommand.
|
||||||
indexOffsetInBytes += 6 * n * 2
|
indexOffsetInBytes += c.NumElements() * 2 // 2 is uint16 size in bytes
|
||||||
}
|
}
|
||||||
if 0 < numc {
|
if 0 < numc {
|
||||||
// Call glFlush to prevent black flicking (especially on Android (#226) and iOS).
|
// Call glFlush to prevent black flicking (especially on Android (#226) and iOS).
|
||||||
@ -198,6 +199,7 @@ type drawImageCommand struct {
|
|||||||
dst *Image
|
dst *Image
|
||||||
src *Image
|
src *Image
|
||||||
nvertices int
|
nvertices int
|
||||||
|
nelements int
|
||||||
color *affine.ColorM
|
color *affine.ColorM
|
||||||
mode opengl.CompositeMode
|
mode opengl.CompositeMode
|
||||||
filter Filter
|
filter Filter
|
||||||
@ -218,13 +220,12 @@ func (c *drawImageCommand) Exec(indexOffsetInBytes int) error {
|
|||||||
|
|
||||||
opengl.GetContext().BlendFunc(c.mode)
|
opengl.GetContext().BlendFunc(c.mode)
|
||||||
|
|
||||||
n := c.quadsNum()
|
if c.nelements == 0 {
|
||||||
if n == 0 {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
proj := f.projectionMatrix()
|
proj := f.projectionMatrix()
|
||||||
theOpenGLState.useProgram(proj, c.src.texture.native, c.dst, c.src, c.color, c.filter)
|
theOpenGLState.useProgram(proj, c.src.texture.native, c.dst, c.src, c.color, c.filter)
|
||||||
opengl.GetContext().DrawElements(opengl.Triangles, 6*n, indexOffsetInBytes)
|
opengl.GetContext().DrawElements(opengl.Triangles, c.nelements, indexOffsetInBytes)
|
||||||
|
|
||||||
// glFlush() might be necessary at least on MacBook Pro (a smilar problem at #419),
|
// glFlush() might be necessary at least on MacBook Pro (a smilar problem at #419),
|
||||||
// but basically this pass the tests (esp. TestImageTooManyFill).
|
// but basically this pass the tests (esp. TestImageTooManyFill).
|
||||||
@ -237,10 +238,18 @@ func (c *drawImageCommand) NumVertices() int {
|
|||||||
return c.nvertices
|
return c.nvertices
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *drawImageCommand) NumElements() int {
|
||||||
|
return c.nelements
|
||||||
|
}
|
||||||
|
|
||||||
func (c *drawImageCommand) AddNumVertices(n int) {
|
func (c *drawImageCommand) AddNumVertices(n int) {
|
||||||
c.nvertices += n
|
c.nvertices += n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *drawImageCommand) AddNumElements(n int) {
|
||||||
|
c.nelements += n
|
||||||
|
}
|
||||||
|
|
||||||
// split splits the drawImageCommand c into two drawImageCommands.
|
// split splits the drawImageCommand c into two drawImageCommands.
|
||||||
//
|
//
|
||||||
// split is called when the number of vertices reaches of the maximum and
|
// split is called when the number of vertices reaches of the maximum and
|
||||||
@ -252,6 +261,8 @@ func (c *drawImageCommand) split(quadsNum int) [2]*drawImageCommand {
|
|||||||
n := quadsNum * QuadVertexSizeInBytes() / s
|
n := quadsNum * QuadVertexSizeInBytes() / s
|
||||||
c1.nvertices = n
|
c1.nvertices = n
|
||||||
c2.nvertices -= n
|
c2.nvertices -= n
|
||||||
|
c1.nelements = 6 * quadsNum
|
||||||
|
c2.nelements -= 6 * quadsNum
|
||||||
return [2]*drawImageCommand{&c1, &c2}
|
return [2]*drawImageCommand{&c1, &c2}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,9 +316,16 @@ func (c *replacePixelsCommand) NumVertices() int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *replacePixelsCommand) NumElements() int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
func (c *replacePixelsCommand) AddNumVertices(n int) {
|
func (c *replacePixelsCommand) AddNumVertices(n int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *replacePixelsCommand) AddNumElements(n int) {
|
||||||
|
}
|
||||||
|
|
||||||
func (c *replacePixelsCommand) CanMerge(dst, src *Image, color *affine.ColorM, mode opengl.CompositeMode, filter Filter) bool {
|
func (c *replacePixelsCommand) CanMerge(dst, src *Image, color *affine.ColorM, mode opengl.CompositeMode, filter Filter) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -333,9 +351,16 @@ func (c *disposeCommand) NumVertices() int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *disposeCommand) NumElements() int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
func (c *disposeCommand) AddNumVertices(n int) {
|
func (c *disposeCommand) AddNumVertices(n int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *disposeCommand) AddNumElements(n int) {
|
||||||
|
}
|
||||||
|
|
||||||
func (c *disposeCommand) CanMerge(dst, src *Image, color *affine.ColorM, mode opengl.CompositeMode, filter Filter) bool {
|
func (c *disposeCommand) CanMerge(dst, src *Image, color *affine.ColorM, mode opengl.CompositeMode, filter Filter) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -382,9 +407,16 @@ func (c *newImageCommand) NumVertices() int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *newImageCommand) NumElements() int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
func (c *newImageCommand) AddNumVertices(n int) {
|
func (c *newImageCommand) AddNumVertices(n int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *newImageCommand) AddNumElements(n int) {
|
||||||
|
}
|
||||||
|
|
||||||
func (c *newImageCommand) CanMerge(dst, src *Image, color *affine.ColorM, mode opengl.CompositeMode, filter Filter) bool {
|
func (c *newImageCommand) CanMerge(dst, src *Image, color *affine.ColorM, mode opengl.CompositeMode, filter Filter) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -410,9 +442,16 @@ func (c *newScreenFramebufferImageCommand) NumVertices() int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *newScreenFramebufferImageCommand) NumElements() int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
func (c *newScreenFramebufferImageCommand) AddNumVertices(n int) {
|
func (c *newScreenFramebufferImageCommand) AddNumVertices(n int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *newScreenFramebufferImageCommand) AddNumElements(n int) {
|
||||||
|
}
|
||||||
|
|
||||||
func (c *newScreenFramebufferImageCommand) CanMerge(dst, src *Image, color *affine.ColorM, mode opengl.CompositeMode, filter Filter) bool {
|
func (c *newScreenFramebufferImageCommand) CanMerge(dst, src *Image, color *affine.ColorM, mode opengl.CompositeMode, filter Filter) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
indicesNum = 1 << 16
|
indicesNum = (1 << 16) / 3 * 3 // Adjust num for triangles.
|
||||||
maxTriangles = indicesNum / 3
|
maxTriangles = indicesNum / 3
|
||||||
maxQuads = maxTriangles / 2
|
maxQuads = maxTriangles / 2
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user