simplified cursor rendering

This commit is contained in:
Liam Galvin 2018-08-31 20:24:58 +01:00
parent 54c2aed4a5
commit e673e72ad9
7 changed files with 71 additions and 134 deletions

View File

@ -5,7 +5,7 @@ import (
"runtime" "runtime"
"time" "time"
"github.com/liamg/glfont" "gitlab.com/liamg/raft/glfont"
"github.com/go-gl/gl/all-core/gl" "github.com/go-gl/gl/all-core/gl"
"github.com/go-gl/glfw/v3.2/glfw" "github.com/go-gl/glfw/v3.2/glfw"
@ -26,7 +26,6 @@ type GUI struct {
fontScale int32 fontScale int32
renderer Renderer renderer Renderer
colourAttr uint32 colourAttr uint32
renderState *RenderState
} }
func New(config *config.Config, terminal *terminal.Terminal, logger *zap.SugaredLogger) *GUI { func New(config *config.Config, terminal *terminal.Terminal, logger *zap.SugaredLogger) *GUI {
@ -39,7 +38,6 @@ func New(config *config.Config, terminal *terminal.Terminal, logger *zap.Sugared
height: 300, height: 300,
terminal: terminal, terminal: terminal,
fontScale: 15.0, fontScale: 15.0,
renderState: NewRenderState(),
} }
} }
@ -73,9 +71,6 @@ func (gui *GUI) resize(w *glfw.Window, width int, height int) {
gui.logger.Errorf("Failed to resize terminal to %d cols, %d rows: %s", cols, rows, err) gui.logger.Errorf("Failed to resize terminal to %d cols, %d rows: %s", cols, rows, err)
} }
gui.logger.Debugf("Resetting render state...")
gui.renderState.Reset()
gui.logger.Debugf("Setting viewport size...") gui.logger.Debugf("Setting viewport size...")
gl.Viewport(0, 0, int32(gui.width), int32(gui.height)) gl.Viewport(0, 0, int32(gui.width), int32(gui.height))
@ -192,9 +187,6 @@ func (gui *GUI) Render() error {
defaultCell := buffer.NewBackgroundCell(gui.config.ColourScheme.Background) defaultCell := buffer.NewBackgroundCell(gui.config.ColourScheme.Background)
var lastCursorX uint
var lastCursorY uint
for !gui.window.ShouldClose() { for !gui.window.ShouldClose() {
dirty := false dirty := false
@ -210,29 +202,16 @@ func (gui *GUI) Render() error {
default: default:
} }
gl.UseProgram(program)
if dirty || gui.terminal.CheckDirty() { if dirty || gui.terminal.CheckDirty() {
gl.UseProgram(program)
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)
if gui.terminal.Modes().ShowCursor {
cx := uint(gui.terminal.GetLogicalCursorX())
cy := uint(gui.terminal.GetLogicalCursorY())
cy = cy + uint(gui.terminal.GetScrollOffset())
if lastCursorX != cx || lastCursorY != cy {
gui.renderState.SetDirty(lastCursorX, lastCursorY)
dirty = true
}
}
lines := gui.terminal.GetVisibleLines() lines := gui.terminal.GetVisibleLines()
lineCount := gui.terminal.ActiveBuffer().ViewHeight() lineCount := gui.terminal.ActiveBuffer().ViewHeight()
colCount := gui.terminal.ActiveBuffer().ViewWidth() colCount := gui.terminal.ActiveBuffer().ViewWidth()
for y := 0; y < int(lineCount); y++ {
for x := 0; x < int(colCount); x++ { for x := 0; x < int(colCount); x++ {
for y := 0; y < int(lineCount); y++ {
cell := defaultCell cell := defaultCell
@ -246,7 +225,27 @@ func (gui *GUI) Render() error {
} }
} }
gui.renderer.DrawCell(cell, uint(x), uint(y)) gui.renderer.DrawCellBg(cell, uint(x), uint(y))
}
}
for x := 0; x < int(colCount); x++ {
for y := 0; y < int(lineCount); y++ {
cell := defaultCell
if y < len(lines) {
cells := lines[y].Cells()
if x < len(cells) {
cell = cells[x]
if cell.Rune() == 0 {
cell = defaultCell
}
}
}
gui.renderer.DrawCellText(cell, uint(x), uint(y))
} }
} }

View File

@ -5,14 +5,15 @@ import (
"math" "math"
"github.com/go-gl/gl/all-core/gl" "github.com/go-gl/gl/all-core/gl"
"github.com/liamg/glfont"
"gitlab.com/liamg/raft/buffer" "gitlab.com/liamg/raft/buffer"
"gitlab.com/liamg/raft/config" "gitlab.com/liamg/raft/config"
"gitlab.com/liamg/raft/glfont"
) )
type Renderer interface { type Renderer interface {
SetArea(areaX int, areaY int, areaWidth int, areaHeight int) SetArea(areaX int, areaY int, areaWidth int, areaHeight int)
DrawCell(cell buffer.Cell, col uint, row uint) DrawCellBg(cell buffer.Cell, col uint, row uint)
DrawCellText(cell buffer.Cell, col uint, row uint)
DrawCursor(col uint, row uint, colour config.Colour) DrawCursor(col uint, row uint, colour config.Colour)
GetTermSize() (uint, uint) GetTermSize() (uint, uint)
} }
@ -89,6 +90,12 @@ func (r *OpenGLRenderer) newRectangle(x float32, y float32, colourAttr uint32) *
return rect return rect
} }
func (rect *rectangle) Draw() {
gl.UseProgram(rect.prog)
gl.BindVertexArray(rect.vao)
gl.DrawArrays(gl.TRIANGLES, 0, 6)
}
func (rect *rectangle) setColour(colour [3]float32) { func (rect *rectangle) setColour(colour [3]float32) {
if rect.colour == colour { if rect.colour == colour {
return return
@ -199,55 +206,44 @@ func (r *OpenGLRenderer) generateRectangle(col uint, line uint) *rectangle {
} }
func (r *OpenGLRenderer) DrawCursor(col uint, row uint, colour config.Colour) { func (r *OpenGLRenderer) DrawCursor(col uint, row uint, colour config.Colour) {
rect := r.getRectangle(col, row)
rect, ok := r.rectangles[[2]uint{col, row}]
if !ok { // probably trying to draw during resize - perhaps add a mutex?
return
}
solid := true
mode := uint32(gl.LINE_LOOP) // gl.TRIANGES for solid cursor
points := int32(4)
if solid {
mode = gl.TRIANGLES
points = 6
}
gl.UseProgram(r.program)
rect.setColour(colour) rect.setColour(colour)
gl.BindVertexArray(rect.vao) rect.Draw()
//gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL)
gl.DrawArrays(mode, 0, points)
//gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL)
} }
func (r *OpenGLRenderer) DrawCell(cell buffer.Cell, col uint, row uint) { func (r *OpenGLRenderer) DrawCellBg(cell buffer.Cell, col uint, row uint) {
var fg [3]float32
var bg [3]float32 var bg [3]float32
if cell.Attr().Reverse { if cell.Attr().Reverse {
fg = cell.Bg()
bg = cell.Fg() bg = cell.Fg()
} else { } else {
fg = cell.Fg()
bg = cell.Bg() bg = cell.Bg()
} }
if bg != r.config.ColourScheme.Background {
rect := r.getRectangle(col, row)
rect.setColour(bg)
rect.Draw()
}
}
func (r *OpenGLRenderer) DrawCellText(cell buffer.Cell, col uint, row uint) {
var fg [3]float32
if cell.Attr().Reverse {
fg = cell.Bg()
} else {
fg = cell.Fg()
}
pos, ok := r.cellPositions[[2]uint{col, row}] pos, ok := r.cellPositions[[2]uint{col, row}]
if !ok { if !ok {
panic(fmt.Sprintf("Missing position data for cell at %d,%d", col, row)) panic(fmt.Sprintf("Missing position data for cell at %d,%d", col, row))
} }
rect := r.getRectangle(col, row)
rect.setColour(bg)
gl.UseProgram(r.program)
gl.BindVertexArray(rect.vao)
gl.DrawArrays(gl.TRIANGLES, 0, 6)
var alpha float32 = 1 var alpha float32 = 1
if cell.Attr().Dim { if cell.Attr().Dim {
alpha = 0.5 alpha = 0.5

View File

@ -1,58 +0,0 @@
package gui
type RenderState struct {
cells map[[2]uint]RenderedCell
}
func NewRenderState() *RenderState {
return &RenderState{
cells: map[[2]uint]RenderedCell{},
}
}
type RenderedCell struct {
bg [3]float32
fg [3]float32
contents rune
dirty bool
}
func (rs *RenderState) Reset() {
rs.cells = map[[2]uint]RenderedCell{}
}
func (rs *RenderState) SetDirty(x uint, y uint) {
rs.cells[[2]uint{x, y}] = RenderedCell{
bg: [3]float32{0, 0, 0},
fg: [3]float32{0, 0, 0},
contents: 0,
dirty: true,
}
}
func (rs *RenderState) RequiresRender(x uint, y uint, bg [3]float32, fg [3]float32, contents rune, empty bool) bool {
state, found := rs.cells[[2]uint{x, y}]
if !found {
if empty {
//return false
}
rs.cells[[2]uint{x, y}] = RenderedCell{
bg: bg,
fg: fg,
contents: contents,
}
return true
}
if state.bg != bg || state.fg != fg || state.contents != contents || state.dirty {
rs.cells[[2]uint{x, y}] = RenderedCell{
bg: bg,
fg: fg,
contents: contents,
}
return true
}
return false
}