Added more efficient damage buffer method

This commit is contained in:
Sasha Koshka 2022-11-17 00:26:28 -05:00
parent 754017a2db
commit 51fbd8acef
2 changed files with 31 additions and 23 deletions

View File

@ -46,9 +46,8 @@ func (backend *Backend) drawCells (forceRedraw bool) (areas []image.Rectangle) {
for y := 0; y < height; y ++ { for y := 0; y < height; y ++ {
for x := 0; x < width; x ++ { for x := 0; x < width; x ++ {
if !forceRedraw && backend.application.Clean(x, y) { continue } if !forceRedraw && backend.application.Clean(x, y) { continue }
backend.application.MarkClean(x, y)
cell := backend.application.Cell(x, y) cell := backend.application.GetForRendering(x, y)
content := cell.Rune() content := cell.Rune()
if forceRedraw && content < 32 { continue } if forceRedraw && content < 32 { continue }
@ -93,13 +92,24 @@ func (backend *Backend) drawRune (
if character < 32 { return } if character < 32 { return }
origin := backend.originOfCell(x, y + 1) origin := backend.originOfCell(x, y + 1)
destinationRectangle, mask, maskPoint, _, _ := backend.font.face.Glyph ( destinationRectangle, mask, maskPoint, _, ok := backend.font.face.Glyph (
fixed.Point26_6 { fixed.Point26_6 {
X: fixed.I(origin.X), X: fixed.I(origin.X),
Y: fixed.I(origin.Y - backend.metrics.descent), Y: fixed.I(origin.Y - backend.metrics.descent),
}, },
character) character)
if !ok {
println("warning")
strokeRectangle (
&image.Uniform {
C: backend.config.Color(stone.ColorForeground),
},
backend.canvas,
backend.boundsOfCell(x, y))
return
}
if backend.drawCellBounds { if backend.drawCellBounds {
strokeRectangle ( strokeRectangle (
&image.Uniform { &image.Uniform {

View File

@ -69,8 +69,8 @@ type Buffer interface {
// dirty by default, are only clean when marked as clean, and become dirty again // dirty by default, are only clean when marked as clean, and become dirty again
// when they are altered in some way. // when they are altered in some way.
type DamageBuffer struct { type DamageBuffer struct {
content []Cell content []Cell
clean []bool onScreen []Cell
width int width int
height int height int
@ -127,9 +127,7 @@ func (buffer *DamageBuffer) SetColor (x, y int, color Color) {
defer buffer.lock.RUnlock() defer buffer.lock.RUnlock()
if buffer.isOutOfBounds(x, y) { return } if buffer.isOutOfBounds(x, y) { return }
index := x + y * buffer.width buffer.content[x + y * buffer.width].color = color
buffer.clean[index] = buffer.content[index].color == color
buffer.content[index].color = color
} }
// SetSize sets the width and height of the buffer. This clears all data in the // SetSize sets the width and height of the buffer. This clears all data in the
@ -139,10 +137,10 @@ func (buffer *DamageBuffer) SetSize (width, height int) {
defer buffer.lock.Unlock() defer buffer.lock.Unlock()
if width < 0 || height < 0 { return } if width < 0 || height < 0 { return }
buffer.width = width buffer.width = width
buffer.height = height buffer.height = height
buffer.content = make([]Cell, width * height) buffer.content = make([]Cell, width * height)
buffer.clean = make([]bool, width * height) buffer.onScreen = make([]Cell, width * height)
for index := 0; index < len(buffer.content); index ++ { for index := 0; index < len(buffer.content); index ++ {
buffer.content[index].color = ColorForeground buffer.content[index].color = ColorForeground
} }
@ -154,9 +152,7 @@ func (buffer *DamageBuffer) SetStyle (x, y int, style Style) {
defer buffer.lock.RUnlock() defer buffer.lock.RUnlock()
if buffer.isOutOfBounds(x, y) { return } if buffer.isOutOfBounds(x, y) { return }
index := x + y * buffer.width buffer.content[x + y * buffer.width].style = style
buffer.clean[index] = buffer.content[index].style == style
buffer.content[index].style = style
} }
// SetRune sets the rune of the cell at the specified x and y coordinates. // SetRune sets the rune of the cell at the specified x and y coordinates.
@ -173,7 +169,6 @@ func (buffer *DamageBuffer) Clear () {
defer buffer.lock.RUnlock() defer buffer.lock.RUnlock()
for index := 0; index < len(buffer.content); index ++ { for index := 0; index < len(buffer.content); index ++ {
buffer.clean[index] = false
buffer.content[index] = Cell { buffer.content[index] = Cell {
color: ColorForeground, color: ColorForeground,
} }
@ -182,9 +177,7 @@ func (buffer *DamageBuffer) Clear () {
func (buffer *DamageBuffer) setRune (x, y int, content rune) { func (buffer *DamageBuffer) setRune (x, y int, content rune) {
if buffer.isOutOfBounds(x, y) { return } if buffer.isOutOfBounds(x, y) { return }
index := x + y * buffer.width buffer.content[x + y * buffer.width].content = content
buffer.clean[index] = buffer.content[index].content == content
buffer.content[index].content = content
} }
// Write writes data stored in a byte slice to the buffer at the current dot // Write writes data stored in a byte slice to the buffer at the current dot
@ -212,15 +205,20 @@ func (buffer *DamageBuffer) Clean (x, y int) (clean bool) {
defer buffer.lock.RUnlock() defer buffer.lock.RUnlock()
if buffer.isOutOfBounds(x, y) { return } if buffer.isOutOfBounds(x, y) { return }
clean = buffer.clean[x + y * buffer.width] index := x + y * buffer.width
clean = buffer.content[index] == buffer.onScreen[index]
return return
} }
// MarkClean marks the cell at the specified x and y coordinates as clean. // GetForRendering returns the cell at the specified x and y coordinates and
func (buffer *DamageBuffer) MarkClean (x, y int) { // marks it as clean.
func (buffer *DamageBuffer) GetForRendering (x, y int) (cell Cell) {
buffer.lock.RLock() buffer.lock.RLock()
defer buffer.lock.RUnlock() defer buffer.lock.RUnlock()
if buffer.isOutOfBounds(x, y) { return } if buffer.isOutOfBounds(x, y) { return }
buffer.clean[x + y * buffer.width] = true index := x + y * buffer.width
buffer.onScreen[index] = buffer.content[index]
cell = buffer.content[index]
return
} }