mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-27 11:12:44 +01:00
graphics: Refactoring: Remove command groups
This commit is contained in:
parent
9d87622a19
commit
c9dd04d471
@ -87,14 +87,43 @@ func (q *commandQueue) appendElements(e0, e1, e2, e3, e4, e5 uint16) {
|
|||||||
q.nelements += 6
|
q.nelements += 6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q *commandQueue) doEnqueueDrawImageCommand(dst, src *Image, nvertices, nelements int, color *affine.ColorM, mode opengl.CompositeMode, filter Filter, forceNewCommand bool) {
|
||||||
|
if nelements > indicesNum {
|
||||||
|
panic("not implemented for too many elements")
|
||||||
|
}
|
||||||
|
if !forceNewCommand && 0 < len(q.commands) {
|
||||||
|
if last := q.commands[len(q.commands)-1]; last.CanMerge(dst, src, color, mode, filter) {
|
||||||
|
last.AddNumVertices(nvertices)
|
||||||
|
last.AddNumElements(nelements)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c := &drawImageCommand{
|
||||||
|
dst: dst,
|
||||||
|
src: src,
|
||||||
|
nvertices: nvertices,
|
||||||
|
nelements: nelements,
|
||||||
|
color: color,
|
||||||
|
mode: mode,
|
||||||
|
filter: filter,
|
||||||
|
}
|
||||||
|
q.commands = append(q.commands, c)
|
||||||
|
}
|
||||||
|
|
||||||
// EnqueueDrawImageCommand enqueues a drawing-image command.
|
// EnqueueDrawImageCommand enqueues a drawing-image command.
|
||||||
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)
|
||||||
nelements := 6 * len(vertices) * opengl.Float.SizeInBytes() / QuadVertexSizeInBytes()
|
nelements := 6 * len(vertices) * opengl.Float.SizeInBytes() / QuadVertexSizeInBytes()
|
||||||
|
nv := 0
|
||||||
|
ne := 0
|
||||||
for i := 0; i < nelements/6; i++ {
|
for i := 0; i < nelements/6; i++ {
|
||||||
if q.nelements%indicesNum > (q.nelements+6)%indicesNum {
|
if q.nelements%indicesNum >= (q.nelements+6)%indicesNum {
|
||||||
q.nextIndex = 0
|
q.nextIndex = 0
|
||||||
|
// Note that even if ne == 0, that's fine.
|
||||||
|
q.doEnqueueDrawImageCommand(dst, src, nv, ne, color, mode, filter, true)
|
||||||
|
nv = 0
|
||||||
|
ne = 0
|
||||||
}
|
}
|
||||||
q.appendElements(
|
q.appendElements(
|
||||||
uint16(q.nextIndex+0),
|
uint16(q.nextIndex+0),
|
||||||
@ -105,25 +134,10 @@ func (q *commandQueue) EnqueueDrawImageCommand(dst, src *Image, vertices []float
|
|||||||
uint16(q.nextIndex+3),
|
uint16(q.nextIndex+3),
|
||||||
)
|
)
|
||||||
q.nextIndex += 4
|
q.nextIndex += 4
|
||||||
|
nv += QuadVertexSizeInBytes() / opengl.Float.SizeInBytes()
|
||||||
|
ne += 6
|
||||||
}
|
}
|
||||||
if 0 < len(q.commands) {
|
q.doEnqueueDrawImageCommand(dst, src, nv, ne, color, mode, filter, false)
|
||||||
last := q.commands[len(q.commands)-1]
|
|
||||||
if last.CanMerge(dst, src, color, mode, filter) {
|
|
||||||
last.AddNumVertices(len(vertices))
|
|
||||||
last.AddNumElements(nelements)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c := &drawImageCommand{
|
|
||||||
dst: dst,
|
|
||||||
src: src,
|
|
||||||
nvertices: len(vertices),
|
|
||||||
nelements: nelements,
|
|
||||||
color: color,
|
|
||||||
mode: mode,
|
|
||||||
filter: filter,
|
|
||||||
}
|
|
||||||
q.commands = append(q.commands, c)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enqueue enqueues a drawing command other than a draw-image command.
|
// Enqueue enqueues a drawing command other than a draw-image command.
|
||||||
@ -133,63 +147,38 @@ func (q *commandQueue) Enqueue(command command) {
|
|||||||
q.commands = append(q.commands, command)
|
q.commands = append(q.commands, command)
|
||||||
}
|
}
|
||||||
|
|
||||||
// commandGroups separates q.commands into some groups.
|
|
||||||
// The number of quads of drawImageCommand in one groups must be equal to or less than
|
|
||||||
// its limit (maxQuads).
|
|
||||||
func (q *commandQueue) commandGroups() [][]command {
|
|
||||||
cs := q.commands
|
|
||||||
var gs [][]command
|
|
||||||
quads := 0
|
|
||||||
for 0 < len(cs) {
|
|
||||||
if len(gs) == 0 {
|
|
||||||
gs = append(gs, []command{})
|
|
||||||
}
|
|
||||||
c := cs[0]
|
|
||||||
switch c := c.(type) {
|
|
||||||
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() {
|
|
||||||
quads += c.quadsNum()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
cc := c.split(maxQuads - quads)
|
|
||||||
gs[len(gs)-1] = append(gs[len(gs)-1], cc[0])
|
|
||||||
cs[0] = cc[1]
|
|
||||||
quads = 0
|
|
||||||
gs = append(gs, []command{})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
gs[len(gs)-1] = append(gs[len(gs)-1], c)
|
|
||||||
cs = cs[1:]
|
|
||||||
}
|
|
||||||
return gs
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flush flushes the command queue.
|
// Flush flushes the command queue.
|
||||||
func (q *commandQueue) Flush() error {
|
func (q *commandQueue) Flush() error {
|
||||||
// glViewport must be called at least at every frame on iOS.
|
// glViewport must be called at least at every frame on iOS.
|
||||||
opengl.GetContext().ResetViewportSize()
|
opengl.GetContext().ResetViewportSize()
|
||||||
nv := 0
|
es := q.elements
|
||||||
lastNv := 0
|
vs := q.vertices
|
||||||
ne := 0
|
for len(q.commands) > 0 {
|
||||||
lastNe := 0
|
nv := 0
|
||||||
for _, g := range q.commandGroups() {
|
ne := 0
|
||||||
for _, c := range g {
|
nc := 0
|
||||||
|
for _, c := range q.commands {
|
||||||
|
if c.NumElements() > indicesNum {
|
||||||
|
panic("not reached")
|
||||||
|
}
|
||||||
|
if ne+c.NumElements() > indicesNum {
|
||||||
|
break
|
||||||
|
}
|
||||||
nv += c.NumVertices()
|
nv += c.NumVertices()
|
||||||
ne += c.NumElements()
|
ne += c.NumElements()
|
||||||
|
nc++
|
||||||
}
|
}
|
||||||
if 0 < ne-lastNe {
|
if 0 < ne {
|
||||||
// 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.elements[lastNe:ne])
|
opengl.GetContext().ElementArrayBufferSubData(es[:ne])
|
||||||
opengl.GetContext().ArrayBufferSubData(q.vertices[lastNv:nv])
|
opengl.GetContext().ArrayBufferSubData(vs[:nv])
|
||||||
|
es = es[ne:]
|
||||||
|
vs = vs[nv:]
|
||||||
}
|
}
|
||||||
numc := len(g)
|
|
||||||
indexOffsetInBytes := 0
|
indexOffsetInBytes := 0
|
||||||
for _, c := range g {
|
for _, c := range q.commands[:nc] {
|
||||||
if err := c.Exec(indexOffsetInBytes); err != nil {
|
if err := c.Exec(indexOffsetInBytes); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -198,12 +187,11 @@ func (q *commandQueue) Flush() error {
|
|||||||
// introduced than drawImageCommand.
|
// introduced than drawImageCommand.
|
||||||
indexOffsetInBytes += c.NumElements() * 2 // 2 is uint16 size in bytes
|
indexOffsetInBytes += c.NumElements() * 2 // 2 is uint16 size in bytes
|
||||||
}
|
}
|
||||||
if 0 < numc {
|
if 0 < nc {
|
||||||
// Call glFlush to prevent black flicking (especially on Android (#226) and iOS).
|
// Call glFlush to prevent black flicking (especially on Android (#226) and iOS).
|
||||||
opengl.GetContext().Flush()
|
opengl.GetContext().Flush()
|
||||||
}
|
}
|
||||||
lastNv = nv
|
q.commands = q.commands[nc:]
|
||||||
lastNe = ne
|
|
||||||
}
|
}
|
||||||
q.commands = nil
|
q.commands = nil
|
||||||
q.nvertices = 0
|
q.nvertices = 0
|
||||||
@ -273,22 +261,6 @@ func (c *drawImageCommand) AddNumElements(n int) {
|
|||||||
c.nelements += n
|
c.nelements += n
|
||||||
}
|
}
|
||||||
|
|
||||||
// split splits the drawImageCommand c into two drawImageCommands.
|
|
||||||
//
|
|
||||||
// split is called when the number of vertices reaches of the maximum and
|
|
||||||
// a command is needed to be executed as another draw call.
|
|
||||||
func (c *drawImageCommand) split(quadsNum int) [2]*drawImageCommand {
|
|
||||||
c1 := *c
|
|
||||||
c2 := *c
|
|
||||||
s := opengl.Float.SizeInBytes()
|
|
||||||
n := quadsNum * QuadVertexSizeInBytes() / s
|
|
||||||
c1.nvertices = n
|
|
||||||
c2.nvertices -= n
|
|
||||||
c1.nelements = 6 * quadsNum
|
|
||||||
c2.nelements -= 6 * quadsNum
|
|
||||||
return [2]*drawImageCommand{&c1, &c2}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CanMerge returns a boolean value indicating whether the other drawImageCommand can be merged
|
// CanMerge returns a boolean value indicating whether the other drawImageCommand can be merged
|
||||||
// with the drawImageCommand c.
|
// with the drawImageCommand c.
|
||||||
func (c *drawImageCommand) CanMerge(dst, src *Image, color *affine.ColorM, mode opengl.CompositeMode, filter Filter) bool {
|
func (c *drawImageCommand) CanMerge(dst, src *Image, color *affine.ColorM, mode opengl.CompositeMode, filter Filter) bool {
|
||||||
|
Loading…
Reference in New Issue
Block a user