mirror of https://github.com/liamg/aminal.git
Changes to minimize memory allocations and to ensure OpenGL objects cleanup (#148)
This commit is contained in:
parent
4242442980
commit
43072eb024
|
@ -24,6 +24,7 @@ type Font struct {
|
|||
texture uint32 // Holds the glyph texture id.
|
||||
color color
|
||||
ttf *truetype.Font
|
||||
ttfFace font.Face
|
||||
scale float32
|
||||
linePadding float32
|
||||
lineHeight float32
|
||||
|
@ -51,10 +52,26 @@ func LoadFont(reader io.Reader, scale float32, windowWidth int, windowHeight int
|
|||
//set screen resolution
|
||||
resUniform := gl.GetUniformLocation(program, gl.Str("resolution\x00"))
|
||||
gl.Uniform2f(resUniform, float32(windowWidth), float32(windowHeight))
|
||||
gl.UseProgram(0)
|
||||
|
||||
return LoadTrueTypeFont(program, reader, scale)
|
||||
}
|
||||
|
||||
func (f *Font) Free() {
|
||||
for _, chr := range f.characters {
|
||||
gl.DeleteTextures(1, &chr.textureID)
|
||||
}
|
||||
|
||||
gl.DeleteBuffers(1, &f.vbo)
|
||||
gl.DeleteVertexArrays(1, &f.vao)
|
||||
|
||||
gl.DeleteProgram(f.program)
|
||||
|
||||
f.vbo = 0
|
||||
f.vao = 0
|
||||
f.program = 0
|
||||
}
|
||||
|
||||
//SetColor allows you to set the text color to be used when you draw the text
|
||||
func (f *Font) SetColor(red float32, green float32, blue float32, alpha float32) {
|
||||
f.color.r = red
|
||||
|
@ -223,14 +240,7 @@ func (f *Font) GetRune(r rune) (*character, error) {
|
|||
|
||||
char := new(character)
|
||||
|
||||
//create new face to measure glyph diamensions
|
||||
ttfFace := truetype.NewFace(f.ttf, &truetype.Options{
|
||||
Size: float64(f.scale),
|
||||
DPI: DPI,
|
||||
Hinting: font.HintingFull,
|
||||
})
|
||||
|
||||
gBnd, gAdv, ok := ttfFace.GlyphBounds(r)
|
||||
gBnd, gAdv, ok := f.ttfFace.GlyphBounds(r)
|
||||
if ok != true {
|
||||
return nil, fmt.Errorf("ttf face glyphBounds error")
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/go-gl/gl/all-core/gl"
|
||||
"github.com/golang/freetype/truetype"
|
||||
"golang.org/x/image/font"
|
||||
)
|
||||
|
||||
type character struct {
|
||||
|
@ -17,14 +18,14 @@ type character struct {
|
|||
bearingV int //glyph bearing vertical
|
||||
}
|
||||
|
||||
//LoadTrueTypeFont builds a set of textures based on a ttf files gylphs
|
||||
//LoadTrueTypeFont builds a set of textures based on a ttf files glyphs
|
||||
func LoadTrueTypeFont(program uint32, r io.Reader, scale float32) (*Font, error) {
|
||||
data, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//make Font stuct type
|
||||
//make Font struct type
|
||||
f := new(Font)
|
||||
f.scale = scale
|
||||
f.characters = map[rune]*character{}
|
||||
|
@ -62,5 +63,12 @@ func LoadTrueTypeFont(program uint32, r io.Reader, scale float32) (*Font, error)
|
|||
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
||||
gl.BindVertexArray(0)
|
||||
|
||||
//create new face to measure glyph dimensions
|
||||
f.ttfFace = truetype.NewFace(f.ttf, &truetype.Options {
|
||||
Size: float64(f.scale),
|
||||
DPI: DPI,
|
||||
Hinting: font.HintingFull,
|
||||
})
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
|
|
@ -14,6 +14,26 @@ func NewFontMap(defaultFont *glfont.Font, defaultBoldFont *glfont.Font) *FontMap
|
|||
}
|
||||
}
|
||||
|
||||
func (fm *FontMap) Free() {
|
||||
if fm.defaultFont != nil {
|
||||
fm.defaultFont.Free()
|
||||
fm.defaultFont = nil
|
||||
}
|
||||
|
||||
if fm.defaultBoldFont != nil {
|
||||
fm.defaultBoldFont.Free()
|
||||
fm.defaultBoldFont = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (fm *FontMap) AssignFonts(defaultFont *glfont.Font, defaultBoldFont *glfont.Font) {
|
||||
fm.defaultFont.Free()
|
||||
fm.defaultBoldFont.Free()
|
||||
|
||||
fm.defaultFont = defaultFont
|
||||
fm.defaultBoldFont = defaultBoldFont
|
||||
}
|
||||
|
||||
func (fm *FontMap) UpdateResolution(w int, h int) {
|
||||
fm.defaultFont.UpdateResolution(w, h)
|
||||
fm.defaultBoldFont.UpdateResolution(w, h)
|
||||
|
|
|
@ -40,8 +40,7 @@ func (gui *GUI) loadFonts() error {
|
|||
if gui.fontMap == nil {
|
||||
gui.fontMap = NewFontMap(defaultFont, boldFont)
|
||||
} else {
|
||||
gui.fontMap.defaultFont = defaultFont
|
||||
gui.fontMap.defaultBoldFont = boldFont
|
||||
gui.fontMap.AssignFonts(defaultFont, boldFont)
|
||||
}
|
||||
|
||||
// add special non-ascii fonts here
|
||||
|
|
28
gui/gui.go
28
gui/gui.go
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/liamg/aminal/terminal"
|
||||
"github.com/liamg/aminal/version"
|
||||
"go.uber.org/zap"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type GUI struct {
|
||||
|
@ -413,7 +414,7 @@ func (gui *GUI) redraw(defaultCell buffer.Cell) {
|
|||
|
||||
if y < len(lines) {
|
||||
|
||||
bufStr := ""
|
||||
var builder strings.Builder
|
||||
bold := false
|
||||
dim := false
|
||||
col := 0
|
||||
|
@ -423,14 +424,14 @@ func (gui *GUI) redraw(defaultCell buffer.Cell) {
|
|||
for x := 0; x < colCount; x++ {
|
||||
if x < len(cells) {
|
||||
cell := cells[x]
|
||||
if bufStr != "" && (cell.Attr().Dim != dim || cell.Attr().Bold != bold || colour != cell.Fg()) {
|
||||
if builder.Len() > 0 && (cell.Attr().Dim != dim || cell.Attr().Bold != bold || colour != cell.Fg()) {
|
||||
var alpha float32 = 1.0
|
||||
if dim {
|
||||
alpha = 0.5
|
||||
}
|
||||
gui.renderer.DrawCellText(bufStr, uint(col), uint(y), alpha, colour, bold)
|
||||
gui.renderer.DrawCellText(builder.String(), uint(col), uint(y), alpha, colour, bold)
|
||||
col = x
|
||||
bufStr = ""
|
||||
builder.Reset()
|
||||
}
|
||||
dim = cell.Attr().Dim
|
||||
colour = cell.Fg()
|
||||
|
@ -439,15 +440,15 @@ func (gui *GUI) redraw(defaultCell buffer.Cell) {
|
|||
if r == 0 {
|
||||
r = ' '
|
||||
}
|
||||
bufStr += string(r)
|
||||
builder.WriteRune(r)
|
||||
}
|
||||
}
|
||||
if bufStr != "" {
|
||||
if builder.Len() > 0 {
|
||||
var alpha float32 = 1.0
|
||||
if dim {
|
||||
alpha = 0.5
|
||||
}
|
||||
gui.renderer.DrawCellText(bufStr, uint(col), uint(y), alpha, colour, bold)
|
||||
gui.renderer.DrawCellText(builder.String(), uint(col), uint(y), alpha, colour, bold)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -526,6 +527,10 @@ func (gui *GUI) createWindowWithOpenGLVersion(major int, minor int) (*glfw.Windo
|
|||
return window, nil
|
||||
}
|
||||
|
||||
func (gui *GUI) onDebugMessage(source uint32, gltype uint32, id uint32, severity uint32, length int32, message string, userParam unsafe.Pointer) {
|
||||
gui.logger.Infof("GL debug message: %s", message)
|
||||
}
|
||||
|
||||
// initOpenGL initializes OpenGL and returns an intiialized program.
|
||||
func (gui *GUI) createProgram() (uint32, error) {
|
||||
if err := gl.Init(); err != nil {
|
||||
|
@ -533,6 +538,12 @@ func (gui *GUI) createProgram() (uint32, error) {
|
|||
}
|
||||
gui.logger.Infof("OpenGL version %s", gl.GoStr(gl.GetString(gl.VERSION)))
|
||||
|
||||
if gui.config.DebugMode {
|
||||
// This allows to catch some OpenGL errors
|
||||
gl.DebugMessageCallback(gui.onDebugMessage, nil)
|
||||
gl.Enable(gl.DEBUG_OUTPUT)
|
||||
}
|
||||
|
||||
gui.logger.Debugf("Compiling shaders...")
|
||||
|
||||
vertexShader, err := compileShader(vertexShaderSource, gl.VERTEX_SHADER)
|
||||
|
@ -550,6 +561,9 @@ func (gui *GUI) createProgram() (uint32, error) {
|
|||
gl.AttachShader(prog, fragmentShader)
|
||||
gl.LinkProgram(prog)
|
||||
|
||||
gl.DeleteShader(vertexShader)
|
||||
gl.DeleteShader(fragmentShader)
|
||||
|
||||
return prog, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -155,7 +155,6 @@ func (rect *rectangle) setColour(colour [3]float32) {
|
|||
}
|
||||
|
||||
func (rect *rectangle) Free() {
|
||||
gl.UseProgram(rect.prog)
|
||||
gl.DeleteVertexArrays(1, &rect.vao)
|
||||
gl.DeleteBuffers(1, &rect.vbo)
|
||||
gl.DeleteBuffers(1, &rect.cv)
|
||||
|
@ -183,6 +182,24 @@ func NewOpenGLRenderer(config *config.Config, fontMap *FontMap, areaX int, areaY
|
|||
return r
|
||||
}
|
||||
|
||||
// This method ensures that all OpenGL resources are deleted correctly
|
||||
func (r *OpenGLRenderer) Free() {
|
||||
for _, rect := range r.rectangles {
|
||||
rect.Free()
|
||||
}
|
||||
r.rectangles = map[[2]uint]*rectangle{}
|
||||
|
||||
for _, tex := range r.textureMap {
|
||||
gl.DeleteTextures(1, &tex)
|
||||
}
|
||||
r.textureMap = map[*image.RGBA]uint32{}
|
||||
|
||||
r.fontMap.Free()
|
||||
|
||||
gl.DeleteProgram(r.program)
|
||||
r.program = 0
|
||||
}
|
||||
|
||||
func (r *OpenGLRenderer) GetTermSize() (uint, uint) {
|
||||
return r.termCols, r.termRows
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue