Commit: 3d127a8b48b808b9437a6bac542233daae212af3
Parent: 7451ad886ad12dd0bf84fa6f282433cd5711abaf
Author: Randy Palamar
Date: Sun, 20 Oct 2024 19:09:45 -0600
do terminal layout in the fragment shader
This also properly calculates wide characters and supports
underline/strikethrough. wcwdith was removed (it doesn't even work
correctly to begin with).
debug display is broken for now but will be restored soon.
Diffstat:
M | LICENSE | | | 24 | ------------------------ |
M | build.sh | | | 6 | +++--- |
D | extern/wcwidth.c | | | 181 | ------------------------------------------------------------------------------- |
M | font.c | | | 30 | +++++++++++++++--------------- |
M | frag_render.glsl | | | 94 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ |
M | main.c | | | 10 | ---------- |
M | terminal.c | | | 9 | ++++----- |
M | test.c | | | 37 | ++++++++++++++++++++++++++++++++++--- |
M | util.c | | | 1 | - |
M | util.h | | | 26 | +++++++++++--------------- |
M | vert_render.glsl | | | 36 | +++++++++++++----------------------- |
M | vtgl.c | | | 254 | ++++++++++++++++++++++++++++++++++++------------------------------------------- |
12 files changed, 262 insertions(+), 446 deletions(-)
diff --git a/LICENSE b/LICENSE
@@ -17,27 +17,3 @@ extern/utf8_decode.c has the following license:
Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de>
See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
-
-----------------------------------------------------------------------
-extern/wcwidth.c is licensed as follows:
-
-Copyright © 2005-2020 Rich Felker, et al.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/build.sh b/build.sh
@@ -13,12 +13,12 @@ testcflags="$cflags -O0 -ggdb -D_DEBUG -Wno-unused-function -Wno-undefined-inter
[ ! -s "./config.h" ] && cp config.def.h config.h
-if [ $debug ]; then
+if [ ${debug} ] && [ ${debug} != "0" ]; then
# Hot Reloading/Debugging
- cflags="$cflags -ggdb -D_DEBUG -Wno-unused-function -Wno-undefined-internal"
+ cflags="$cflags -O0 -ggdb -D_DEBUG -Wno-unused-function -Wno-undefined-internal"
#cflags="$cflags -fsanitize=address,undefined"
- libcflags="$cflags -O0 -fPIC"
+ libcflags="$cflags -fPIC"
libldflags="$ldflags -shared"
${cc} $libcflags vtgl.c -o vtgl.so $libldflags
diff --git a/extern/wcwidth.c b/extern/wcwidth.c
@@ -1,181 +0,0 @@
-static const u8 table[] = {
- 16,16,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,16,33,16,16,16,34,35,36,
- 37,38,39,40,16,16,41,16,16,16,16,16,16,16,16,16,16,16,42,43,16,16,44,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,45,16,46,47,48,49,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,50,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,51,16,16,52,
- 53,16,54,55,56,16,16,16,16,16,16,57,16,16,58,16,59,60,61,62,63,64,65,66,67,68,
- 69,70,16,71,72,73,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,74,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,75,76,16,16,16,77,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,78,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,79,80,16,16,16,16,16,16,16,81,16,16,16,16,16,82,83,84,16,16,16,16,16,85,
- 86,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,248,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,254,255,255,255,255,191,182,0,0,0,0,0,0,0,63,0,255,23,0,0,0,0,0,248,255,
- 255,0,0,1,0,0,0,0,0,0,0,0,0,0,0,192,191,159,61,0,0,0,128,2,0,0,0,255,255,255,
- 7,0,0,0,0,0,0,0,0,0,0,192,255,1,0,0,0,0,0,0,248,15,32,0,0,192,251,239,62,0,0,
- 0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,255,255,255,255,
- 255,7,0,0,0,0,0,0,20,254,33,254,0,12,0,0,0,2,0,0,0,0,0,0,16,30,32,0,0,12,0,0,
- 64,6,0,0,0,0,0,0,16,134,57,2,0,0,0,35,0,6,0,0,0,0,0,0,16,190,33,0,0,12,0,0,
- 252,2,0,0,0,0,0,0,144,30,32,64,0,12,0,0,0,4,0,0,0,0,0,0,0,1,32,0,0,0,0,0,0,17,
- 0,0,0,0,0,0,192,193,61,96,0,12,0,0,0,2,0,0,0,0,0,0,144,64,48,0,0,12,0,0,0,3,0,
- 0,0,0,0,0,24,30,32,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,4,92,0,0,0,0,0,0,0,0,0,0,0,
- 242,7,128,127,0,0,0,0,0,0,0,0,0,0,0,0,242,31,0,63,0,0,0,0,0,0,0,0,0,3,0,0,160,
- 2,0,0,0,0,0,0,254,127,223,224,255,254,255,255,255,31,64,0,0,0,0,0,0,0,0,0,0,0,
- 0,224,253,102,0,0,0,195,1,0,30,0,100,32,0,32,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,28,0,0,0,28,0,0,0,12,0,0,0,12,0,0,0,0,0,0,0,176,63,64,254,
- 15,32,0,0,0,0,0,120,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,0,2,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,135,1,4,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 128,9,0,0,0,0,0,0,64,127,229,31,248,159,0,0,0,0,0,0,255,127,0,0,0,0,0,0,0,0,
- 15,0,0,0,0,0,208,23,4,0,0,0,0,248,15,0,3,0,0,0,60,59,0,0,0,0,0,0,64,163,3,0,0,
- 0,0,0,0,240,207,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,255,253,33,16,
- 3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,
- 251,0,248,0,0,0,124,0,0,0,0,0,0,223,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,
- 255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,3,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,
- 0,60,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,128,247,63,0,0,0,192,0,0,0,0,0,0,0,0,0,0,3,0,68,8,0,0,96,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,0,255,255,3,128,0,0,0,0,192,63,0,0,128,255,3,0,
- 0,0,0,0,7,0,0,0,0,0,200,51,0,0,0,0,32,0,0,
- 0,0,0,0,0,0,126,102,0,8,16,0,0,0,0,0,16,0,0,0,0,0,0,157,193,2,0,0,0,0,48,64,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,33,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,0,0,0,
- 64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,255,
- 255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,1,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,110,240,0,
- 0,0,0,0,135,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,0,0,0,0,240,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,255,1,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,255,127,0,0,0,0,0,0,128,
- 3,0,0,0,0,0,120,38,0,32,0,0,0,0,0,0,7,0,0,0,128,239,31,0,0,0,0,0,0,0,8,0,3,0,
- 0,0,0,0,192,127,0,30,0,0,0,0,0,0,0,0,0,0,0,128,211,64,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,128,248,7,0,0,3,0,0,0,0,0,0,24,1,0,0,0,192,31,31,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,255,92,0,0,64,0,0,0,0,0,0,0,0,0,0,248,133,13,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,60,176,1,0,0,48,0,0,0,0,0,0,0,0,0,0,
- 248,167,1,0,0,0,0,0,0,0,0,0,0,0,0,40,191,0,0,0,0,0,0,0,0,0,0,0,0,224,188,15,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,255,6,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,240,12,1,0,0,0,254,7,0,0,0,0,248,121,128,0,126,14,0,0,0,0,0,252,
- 127,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,191,0,0,0,0,0,0,0,0,0,0,252,255,
- 255,252,109,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,126,180,191,0,0,0,0,0,0,0,0,0,163,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,255,
- 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,128,7,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,15,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,3,248,255,231,15,0,0,0,60,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,
- 255,255,255,255,127,248,255,255,255,255,255,31,32,0,16,0,0,248,254,255,0,0,0,
- 0,0,0,0,0,0,0,127,255,255,249,219,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,240,7,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-};
-
-static const u8 wtable[] = {
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,18,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,19,16,20,21,22,16,16,16,23,16,16,24,25,26,27,28,17,
- 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,29,
- 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
- 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
- 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
- 17,17,17,17,17,17,17,17,30,16,16,16,16,31,16,16,17,17,17,17,17,17,17,17,17,17,
- 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
- 17,17,17,17,17,17,17,32,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,16,16,16,33,
- 34,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,35,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
- 17,17,17,17,17,17,36,17,17,37,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,38,39,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
- 16,16,16,16,16,16,16,40,41,42,43,44,45,46,47,16,48,49,16,16,16,16,
- 16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,6,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,48,0,0,0,0,0,0,255,15,0,0,0,0,128,0,0,8,
- 0,2,12,0,96,48,64,16,0,0,4,44,36,32,12,0,0,0,1,0,0,0,80,184,0,0,0,0,0,0,0,224,
- 0,0,0,1,128,0,0,0,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,33,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,251,255,255,255,255,255,255,255,
- 255,255,255,15,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,63,0,0,0,255,15,255,255,255,255,
- 255,255,255,127,254,255,255,255,255,255,255,255,255,255,127,254,255,255,255,
- 255,255,255,255,255,255,255,255,255,224,255,255,255,255,255,254,255,255,255,
- 255,255,255,255,255,255,255,127,255,255,255,255,255,7,255,255,255,255,15,0,
- 255,255,255,255,255,127,255,255,255,255,255,0,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,
- 0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,31,255,255,255,255,255,255,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,
- 255,255,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,15,0,0,0,0,0,0,0,0,0,0,0,0,0,255,3,0,0,255,255,255,255,247,255,127,15,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,255,255,255,255,255,255,255,255,255,255,
- 255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,7,0,255,255,255,127,0,0,0,0,0,
- 0,7,0,240,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 15,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,64,254,7,0,0,0,0,0,0,0,0,0,0,0,0,7,0,255,255,255,
- 255,255,15,255,1,3,0,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,
- 1,224,191,255,255,255,255,255,255,255,255,223,255,255,15,0,255,255,255,255,
- 255,135,15,0,255,255,17,255,255,255,255,255,255,255,255,127,253,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 159,255,255,255,255,255,255,255,63,0,120,255,255,255,0,0,4,0,0,96,0,16,0,0,0,
- 0,0,0,0,0,0,0,248,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,255,255,
- 255,255,255,255,255,255,63,16,39,0,0,24,240,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,255,15,0,
- 0,0,224,255,255,255,255,255,255,255,255,255,255,255,255,123,252,255,255,255,
- 255,231,199,255,255,255,231,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,15,7,7,0,63,0,0,0,0,0,0,0,0,0,0,0,0,0,
-};
-
-static i32 wcwidth(u32 wc)
-{
- if (wc < 0xffU)
- return ((wc+1) & 0x7f) >= 0x21 ? 1 : wc ? -1 : 0;
- if ((wc & 0xfffeffffU) < 0xfffe) {
- if ((table[table[wc>>8]*32+((wc&255)>>3)]>>(wc&7))&1)
- return 0;
- if ((wtable[wtable[wc>>8]*32+((wc&255)>>3)]>>(wc&7))&1)
- return 2;
- return 1;
- }
- if ((wc & 0xfffe) == 0xfffe)
- return -1;
- if (wc-0x20000U < 0x20000)
- return 2;
- if (wc == 0xe0001 || wc-0xe0020U < 0x5f || wc-0xe0100U < 0xef)
- return 0;
- return 1;
-}
diff --git a/font.c b/font.c
@@ -135,7 +135,7 @@ get_and_clear_glyph_cache_stats(GlyphCache *gc)
}
static u32 *
-render_glyph(Arena *a, FontAtlas *fa, u32 cp, enum face_style style, CachedGlyph **out_glyph, u32 *out_idx)
+render_glyph(Arena *a, FontAtlas *fa, u32 cp, enum face_style style, CachedGlyph **out_glyph)
{
BEGIN_TIMED_BLOCK();
GlyphCache *gc = &fa->glyph_cache;
@@ -147,7 +147,6 @@ render_glyph(Arena *a, FontAtlas *fa, u32 cp, enum face_style style, CachedGlyph
u32 idx = get_glyph_entry_index(&fa->glyph_cache, packed_cp);
CachedGlyph *cg = fa->glyph_cache.glyphs + idx;
- *out_idx = idx;
*out_glyph = cg;
if (cg->uploaded_to_gpu)
goto end;
@@ -183,14 +182,13 @@ render_glyph(Arena *a, FontAtlas *fa, u32 cp, enum face_style style, CachedGlyph
/* NOTE: this looks weird but some 'wide' glyphs are not actually wide but still
* need to be displayed as such (eg. ト). x1 can be used to determine this. */
- cg->tile_count = (u16)(width + (fa->info.w + 1) / 2) / fa->info.w;
- if (cg->tile_count * fa->info.w < x1) cg->tile_count++;
+ cg->tile_count = (((i32)x1 - 1) / (i32)fa->info.w) + 1;
+
ASSERT(cg->tile_count * fa->info.w >= x1);
+ ASSERT(cg->tile_count >= 1);
i32 out_width = fa->info.w * cg->tile_count;
i32 out_size = fa->info.h * out_width;
- cg->size.w = out_width;
- cg->size.h = fa->info.h;
ASSERT(out_width >= width);
uv2 tile_coord = unpack_gpu_tile_coord(cg->gpu_tile_index);
@@ -255,20 +253,22 @@ static void
font_atlas_update(FontAtlas *fa, iv2 glyph_bitmap_dim)
{
GlyphCache *gc = &fa->glyph_cache;
- mem_clear(gc->glyphs, 0, sizeof(*gc->glyphs) * gc->cache_len);
- mem_clear(gc->hash_table, 0, sizeof(*gc->hash_table) * gc->cache_len);
+ mem_clear(gc->glyphs, 0, sizeof(*gc->glyphs) * gc->cache_len);
+ mem_clear(gc->hash_table, 0, sizeof(*gc->hash_table) * gc->cache_len);
+ mem_clear(gc->occupied_tiles, 0, sizeof(*gc->occupied_tiles) * gc->cache_len);
get_and_clear_glyph_cache_stats(gc);
- Font *font = &fa->fonts[0][FS_NORMAL];
+ Font *font = &fa->fonts[0][FS_BOLD];
+ if (!font) font = &fa->fonts[0][FS_NORMAL];
i32 x0, x1, y0, y1;
stbtt_GetFontBoundingBox(&font->font_info, &x0, &y0, &x1, &y1);
- f32 scale = font->stbtt_scale;
- fa->info.h = scale * (y1 - y0) + 0.5;
- fa->info.w = scale * (x1 - x0) + 0.5;
- fa->info.baseline = -scale * y0 + 0.5;
+ f32 scale = font->stbtt_scale;
+ fa->info.h = (u32)(scale * (y1 - y0)) + 1;
+ fa->info.w = (u32)(scale * (x1 - x0)) + 1;
+ fa->info.baseline = (u32)(-scale * y0) + 1;
- gc->tiles_in_x = (glyph_bitmap_dim.x - 1) / fa->info.w;
- gc->tiles_in_y = (glyph_bitmap_dim.y - 1) / fa->info.h;
+ gc->tiles_in_x = (glyph_bitmap_dim.x - 1) / fa->info.w - 1;
+ gc->tiles_in_y = (glyph_bitmap_dim.y - 1) / fa->info.h - 1;
ASSERT(gc->tiles_in_x && gc->tiles_in_y);
ASSERT(gc->tiles_in_x * fa->info.w <= glyph_bitmap_dim.x);
diff --git a/frag_render.glsl b/frag_render.glsl
@@ -1,16 +1,25 @@
#version 430 core
-out vec4 colour;
+layout(location = 0) in vec2 pixel_coord;
+layout(location = 1) in vec2 texture_coord;
-in VS_OUT {
- vec2 tex_coord;
- flat int index;
-} fs_in;
+layout(location = 0) out vec4 colour;
+
+struct RenderCell {
+ uint gpu_glyph;
+ uint fg;
+ uint bg;
+};
+
+layout(std430, binding = 0) readonly restrict buffer ssbo_cells {
+ RenderCell cells[];
+};
layout(std140, binding = 0) uniform parameters {
uvec2 cell_size;
- uvec2 term_size;
- uvec2 top_left_margin;
+ uvec2 term_size_in_cells;
+ vec2 term_size_in_pixels;
+ vec2 top_left_margin;
uint margin_colour;
float blink_parameter;
@@ -21,10 +30,7 @@ layout(std140, binding = 0) uniform parameters {
uint underline_max;
};
-uniform sampler2DArray u_texslot;
-uniform int u_charmap[512];
-uniform vec2 u_texscale[512];
-uniform uvec2 u_texcolour[512];
+layout(location = 3) uniform sampler2D u_bitmap_texture;
#define ATTR_MASK 0xFFu
#define ATTR_FAINT (1u << 0u)
@@ -34,29 +40,61 @@ uniform uvec2 u_texcolour[512];
#define ATTR_INVISIBLE (1u << 4u)
#define ATTR_STRUCK (1u << 5u)
+vec2
+unpack_glyph_position(uint glyph_position)
+{
+ vec2 result;
+ result.x = glyph_position & 0xFFFFu;
+ result.y = glyph_position >> 16u;
+ return result;
+}
+
void main()
{
- uint attr = u_texcolour[fs_in.index].x & ATTR_MASK;
- vec3 fg = unpackUnorm4x8(u_texcolour[fs_in.index].x).wzy;
- vec3 bg = unpackUnorm4x8(u_texcolour[fs_in.index].y).wzy;
+ uvec2 cell_index = uvec2((pixel_coord - top_left_margin) / cell_size);
+ vec2 cell_pos = mod((pixel_coord - top_left_margin), cell_size);
- vec3 tex_coord = vec3(fs_in.tex_coord, u_charmap[fs_in.index]);
- tex_coord.xy *= u_texscale[fs_in.index];
+ vec3 result;
+ if (pixel_coord.x > top_left_margin.x && cell_index.x < term_size_in_cells.x &&
+ pixel_coord.y > top_left_margin.y && cell_index.y < term_size_in_cells.y)
+ {
+ RenderCell cell = cells[term_size_in_cells.x * cell_index.y + cell_index.x];
- if ((attr & ATTR_FAINT) != 0) fg *= 0.5;
- /* TODO: this causes a bug with reverse video */
- if ((attr & ATTR_BLINK) != 0) fg *= 0.5 * (1 + sin(blink_parameter));
+ uint attr = cell.fg & ATTR_MASK;
+ vec3 fg = unpackUnorm4x8(cell.fg).wzy;
+ vec3 bg = unpackUnorm4x8(cell.bg).wzy;
- if ((attr & ATTR_INVERSE) != 0) {
- vec3 tmp = fg;
- fg = bg;
- bg = tmp;
- }
+ vec2 glyph_pos = unpack_glyph_position(cell.gpu_glyph) * cell_size;
+ vec2 tex_coord = (glyph_pos + cell_pos) / vec2(textureSize(u_bitmap_texture, 0));
+
+ if ((attr & ATTR_FAINT) != 0) fg *= 0.5;
+ if ((attr & ATTR_BLINK) != 0) fg = mix(bg, fg, 0.5 * (1 + sin(blink_parameter)));
+
+ if ((attr & ATTR_INVERSE) != 0) {
+ vec3 tmp = fg;
+ fg = bg;
+ bg = tmp;
+ }
- vec4 smp = texture(u_texslot, tex_coord);
- float a = u_texscale[fs_in.index].x == 0 ? 0 : smp.a;
+ vec4 smp = texture(u_bitmap_texture, tex_coord);
+ result = mix(bg, fg * smp.xyz, smp.a);
- vec3 result = mix(bg, fg * smp.xyz, a);
+ if (((attr & ATTR_UNDERLINED) != 0) &&
+ cell_pos.y >= underline_min && cell_pos.y < underline_max)
+ result = fg;
- colour = vec4(result, 1);
+ if (((attr & ATTR_STRUCK) != 0) &&
+ cell_pos.y >= strike_min && cell_pos.y < strike_max)
+ result = fg;
+ } else {
+ result = unpackUnorm4x8(margin_colour).wzy;
+ }
+
+ /* NOTE: set to true to see the glyph cache texture */
+ if (false) {
+ vec4 smp = texture(u_bitmap_texture, pixel_coord / term_size_in_pixels);
+ colour = smp;
+ } else {
+ colour = vec4(result, 1);
+ }
}
diff --git a/main.c b/main.c
@@ -142,16 +142,6 @@ init_window(Term *t, Arena arena, iv2 window_size)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
- glGenTextures(1, &t->gl.glyph_tex);
- glBindTexture(GL_TEXTURE_2D_ARRAY, t->gl.glyph_tex);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8,
- MAX_FONT_SIZE, MAX_FONT_SIZE, TEXTURE_GLYPH_COUNT,
- 0, GL_RED, GL_UNSIGNED_BYTE, 0);
-
glGenTextures(1, &t->gl.glyph_bitmap_tex);
glBindTexture(GL_TEXTURE_2D, t->gl.glyph_bitmap_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
diff --git a/terminal.c b/terminal.c
@@ -1225,12 +1225,11 @@ push_line(Term *t, Line *line, Arena a)
if (t->mode & TM_AUTO_WRAP && t->cursor.state & CURSOR_WRAP_NEXT)
push_newline(t, 1);
- i32 width;
+ u32 width;
if (line->has_unicode) {
- /* TODO: this needs to be determined from the CachedGlyph tile count
- * wcwidth does not report the correct result for all characters */
- width = wcwidth(cp);
- ASSERT(width != -1);
+ /* TODO: this is obviously complete crap but wcwidth from libc doesn't
+ * actually work so we must check from the rendered glyph */
+ get_gpu_glyph_index(t->arena_for_frame, &t->gl, &t->fa, cp, FS_NORMAL, &width);
} else {
width = 1;
}
diff --git a/test.c b/test.c
@@ -1,13 +1,39 @@
-#include "vtgl.c"
+#define GL_GLEXT_PROTOTYPES 1
+#include <GLFW/glfw3.h>
+
+#include "util.h"
+#include "config.h"
+
/* NOTE: stubs for stuff we aren't testing */
#undef glfwSetWindowTitle
#undef glfwGetWindowTitle
-void glfwSetWindowTitle(GLFWwindow *w, const char *s) {};
-const char *glfwGetWindowTitle(GLFWwindow *w) { return "test"; };
+void glfwSetWindowTitle(GLFWwindow *w, const char *s) {}
+const char *glfwGetWindowTitle(GLFWwindow *w) { return "test"; }
+
+static void get_gpu_glyph_index(Arena, void *, void *, u32, u32, u32 *);
+static GlyphCacheStats get_and_clear_glyph_cache_stats(void *p) { return (GlyphCacheStats){0}; }
+static void init_font(void *a, void *b) {}
+
+KEYBIND_FN(copy) { return 0; }
+KEYBIND_FN(paste) { return 0; }
+KEYBIND_FN(scroll) { return 0; }
+KEYBIND_FN(zoom) { return 0; }
+
+#include "terminal.c"
+#include "debug.c"
#include <string.h> /* memcmp */
+#include <wchar.h> /* wcwidth */
+
+static void
+get_gpu_glyph_index(Arena a, void *b, void *c, u32 cp, u32 d, u32 *width)
+{
+ /* TODO: this is wrong but will have to do for these tests */
+ *width = wcwidth(cp);
+ ASSERT(*width != -1);
+}
#define ESC(a) s8("\x1B"#a)
#define CSI(a) ESC([a)
@@ -251,6 +277,11 @@ static TEST_FN(working_ringbuffer)
static u32 failure_count;
+#ifdef _DEBUG
+/* NOTE: shut up compiler warning that can't be disabled */
+DebugRecord debug_records[__COUNTER__];
+#endif
+
int
main(void)
{
diff --git a/util.c b/util.c
@@ -191,4 +191,3 @@ utf8_encode(u32 cp)
}
#include "extern/utf8_decode.c"
-#include "extern/wcwidth.c"
diff --git a/util.h b/util.h
@@ -185,11 +185,6 @@ typedef struct {
#define GL_RENDER_UNIFORMS \
X(Pmat) \
- X(charmap) \
- X(texcolour) \
- X(texscale) \
- X(texslot) \
- X(vertoff) \
X(vertscale)
#define GL_POST_UNIFORMS \
@@ -225,9 +220,10 @@ enum shader_stages {
typedef struct {
uv2 cell_size;
- uv2 term_size;
+ uv2 term_size_in_cells;
+ v2 term_size_in_pixels;
- uv2 top_left_margin;
+ v2 top_left_margin;
u32 margin_colour;
f32 blink_parameter;
@@ -237,6 +233,8 @@ typedef struct {
u32 underline_min;
u32 underline_max;
+
+ u32 _pad[2];
} ShaderParameters;
typedef struct {
@@ -268,10 +266,14 @@ typedef struct {
u32 flags;
u32 mode;
-
- u32 glyph_tex;
} GLCtx;
+typedef struct {
+ u32 gpu_glyph;
+ u32 fg;
+ u32 bg;
+} RenderCell;
+
/* NOTE: This must match the number in the shaders & the number glyphs in
* the gpu glyph cache. By doing this we ensure that filling a single push buffer
* will not evict a needed glyph texture from the GPU */
@@ -287,7 +289,6 @@ typedef struct {
#define MIN_FONT_SIZE 8
#define MAX_FONT_SIZE 128
-#define TEXTURE_GLYPH_COUNT PUSH_BUFFER_CAP
enum conversion_status { CR_FAILURE, CR_SUCCESS };
struct conversion_result {
@@ -339,7 +340,6 @@ typedef struct {
i32 baseline;
} FontInfo;
-#define GLYPH_CACHE_LEN PUSH_BUFFER_CAP
typedef struct {
/* distance to shift glyph from bounding box origin */
iv2 delta;
@@ -351,10 +351,6 @@ typedef struct {
u32 cp;
u32 next_with_same_hash;
u32 gpu_tile_index;
- union {
- struct { u16 h, w; };
- struct { u16 x, y; };
- } size;
u16 prev, next;
u16 uploaded_to_gpu;
u16 tile_count;
diff --git a/vert_render.glsl b/vert_render.glsl
@@ -1,31 +1,21 @@
-#version 400 core
+#version 430 core
-in vec2 position;
+layout(location = 0) in vec2 position;
-uniform mat4 u_Pmat;
-uniform vec2 u_vertscale[512];
-uniform vec2 u_vertoff[512];
+layout(location = 0) out vec2 pixel_coord;
+layout(location = 1) out vec2 texture_coord;
-out VS_OUT {
- vec2 tex_coord;
- flat int index;
-} vs_out;
+layout(location = 0) uniform mat4 u_Pmat;
+layout(location = 1) uniform vec2 u_vertscale;
void main()
{
- vec2 scale = u_vertscale[gl_InstanceID];
- vec2 offset = u_vertoff[gl_InstanceID];
+ vec2 pos = position.xy;
+ vec2 scale = u_vertscale;
- mat4 transform = mat4(
- scale.x, 0, 0, 0,
- 0, scale.y, 0, 0,
- 0, 0, 1, 0,
- offset.x, offset.y, 0, 1
- );
-
- gl_Position = u_Pmat * transform * vec4(position, 0.0, 1.0);
-
- vs_out.tex_coord = position;
- vs_out.tex_coord.y = 1.0 - vs_out.tex_coord.y;
- vs_out.index = gl_InstanceID;
+ texture_coord = pos;
+ pixel_coord = pos;
+ pixel_coord.y = 1 - pixel_coord.y;
+ pixel_coord *= scale;
+ gl_Position = u_Pmat * vec4(pos * scale, 0.0, 1.0);
}
diff --git a/vtgl.c b/vtgl.c
@@ -6,6 +6,10 @@
#include "config.h"
#include "font.c"
+
+/* TODO this should be removed */
+static u32 get_gpu_glyph_index(Arena, GLCtx *, FontAtlas *, u32, enum face_style, u32 *);
+
#include "terminal.c"
#ifdef _DEBUG
@@ -66,21 +70,6 @@ get_occupied_size(Term *t)
}
static v2
-get_terminal_top_left(Term *t)
-{
- /* NOTE: There is trade-off here: you can center the usable area which looks good but
- * causes the contents to jump around when resizing; or you can only consider the global
- * padding and have the contents fixed while resizing. We are choosing the former! */
- /* IMPORTANT: Assume the glyphs already have subpixel rendering so cells must be aligned
- * on pixels. No harm if they don't but if they do and we don't align on pixels they
- * will look like crap. */
- v2 os = get_occupied_size(t);
- v2 delta = {.x = t->gl.window_size.w - os.w, .y = t->gl.window_size.h - os.h};
- v2 result = {.x = (u32)(delta.x / 2), .y = (u32)(t->gl.window_size.h - delta.y / 2)};
- return result;
-}
-
-static v2
get_terminal_bot_left(Term *t)
{
v2 os = get_occupied_size(t);
@@ -92,7 +81,8 @@ get_terminal_bot_left(Term *t)
static void
resize(Term *t)
{
- v2 ws = t->gl.window_size;
+ GLCtx *gl = &t->gl;
+ v2 ws = gl->window_size;
ws.w -= 2 * g_term_margin.w;
ws.h -= 2 * g_term_margin.h;
@@ -109,13 +99,29 @@ resize(Term *t)
if (!equal_uv2(old_size, t->size)) {
os_alloc_framebuffer(&t->views[0].fb, t->size.h, t->size.w);
os_alloc_framebuffer(&t->views[1].fb, t->size.h, t->size.w);
- t->gl.flags |= NEEDS_FULL_REFILL;
+ gl->flags |= NEEDS_FULL_REFILL;
}
os_set_term_size(t->child, t->size.h, t->size.w, ws.w, ws.h);
- t->gl.flags &= ~NEEDS_RESIZE;
-}
+ u32 buffer_size = t->size.w * t->size.h * sizeof(RenderCell);
+ glDeleteBuffers(1, &gl->render_shader_ssbo);
+ glGenBuffers(1, &gl->render_shader_ssbo);
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, gl->render_shader_ssbo);
+ glBufferData(GL_SHADER_STORAGE_BUFFER, buffer_size, 0, GL_DYNAMIC_DRAW);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, gl->render_shader_ssbo);
+
+ ShaderParameters *sp = &gl->shader_parameters;
+ sp->cell_size = (uv2){.w = cs.w, .h = cs.h};
+ sp->top_left_margin = g_term_margin;
+ sp->margin_colour = g_colours.data[g_colours.bgidx].rgba;
+ //sp->margin_colour = 0x7f003f00;
+
+ sp->term_size_in_pixels = gl->window_size;
+ sp->term_size_in_cells = t->size;
+
+ gl->flags &= ~NEEDS_RESIZE;
+}
static void
update_uniforms(Term *t, enum shader_stages stage)
{
@@ -140,13 +146,6 @@ update_uniforms(Term *t, enum shader_stages stage)
set_projection_matrix(&t->gl);
}
-static uv2
-unpack_gpu_glyph_index(u32 gpu_glyph_index)
-{
- uv2 result = {.x = gpu_glyph_index & 0xFFFF, .y = gpu_glyph_index >> 16};
- return result;
-}
-
static iv2
get_gpu_texture_position(v2 cs, uv2 gpu_position)
{
@@ -154,24 +153,14 @@ get_gpu_texture_position(v2 cs, uv2 gpu_position)
return result;
}
-static i32
-get_gpu_glyph_index(Arena a, GLCtx *gl, FontAtlas *fa, u32 codepoint, enum face_style style, uv2 *glyph_size)
+static u32
+get_gpu_glyph_index(Arena a, GLCtx *gl, FontAtlas *fa, u32 codepoint, enum face_style style, u32 *tiles)
{
- u32 depth_idx;
CachedGlyph *cg;
- u32 *data = render_glyph(&a, fa, codepoint, style, &cg, &depth_idx);
- *glyph_size = (uv2){.h = cg->size.h, .w = cg->size.w};
+ u32 *data = render_glyph(&a, fa, codepoint, style, &cg);
if (data) {
- ASSERT(depth_idx);
- glBindTexture(GL_TEXTURE_2D_ARRAY, gl->glyph_tex);
- glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, depth_idx,
- glyph_size->w, glyph_size->h, 1, GL_RGBA,
- GL_UNSIGNED_BYTE, data);
cg->uploaded_to_gpu = 1;
- /* TODO: this will be bound beforehand */
- glBindTexture(GL_TEXTURE_2D, gl->glyph_bitmap_tex);
-
uv2 gpu_position = unpack_gpu_tile_coord(cg->gpu_tile_index);
v2 cell_size = get_cell_size(fa);
iv2 glyph_position = get_gpu_texture_position(cell_size, gpu_position);
@@ -181,13 +170,13 @@ get_gpu_glyph_index(Arena a, GLCtx *gl, FontAtlas *fa, u32 codepoint, enum face_
glTexSubImage2D(GL_TEXTURE_2D, 0, glyph_position.x, glyph_position.y,
cell_size.w * cg->tile_count, cell_size.h,
GL_RGBA, GL_UNSIGNED_BYTE, data);
-
- glBindTexture(GL_TEXTURE_2D_ARRAY, gl->glyph_tex);
}
ASSERT(cg->uploaded_to_gpu);
- return depth_idx;
+ *tiles = cg->tile_count;
+ return cg->gpu_tile_index;
}
+#if 0
static void
flush_render_push_buffer(RenderPushBuffer *rpb, GLCtx *gl)
{
@@ -243,119 +232,99 @@ draw_rectangle(RenderPushBuffer *rpb, GLCtx *gl, Rect r, Colour colour)
{
push_char(rpb, gl, r.size, r.pos, (v2){0}, (uv2){.y = colour.rgba}, 0);
}
+#endif
-static void
-push_cell(RenderPushBuffer *rpb, GLCtx *gl, FontAtlas *fa, Arena a, Cell c, Rect r)
-{
- BEGIN_TIMED_BLOCK();
- u32 idx = get_render_push_buffer_idx(rpb, gl, 2);
-
- ASSERT(c.cp);
- uv2 g_size;
- i32 depth_idx = get_gpu_glyph_index(a, gl, fa, c.cp, c.style.attr & FS_MASK, &g_size);
-
- rpb->vertscales[idx + 0] = r.size;
- rpb->vertscales[idx + 1] = (v2){.x = g_size.w, .y = g_size.h};
-
- rpb->vertoffsets[idx + 0] = r.pos;
- rpb->vertoffsets[idx + 1] = r.pos;
-
- rpb->texscales[idx + 0] = (v2){0};
- rpb->texscales[idx + 1] = (v2){
- .x = g_size.w / (f32)MAX_FONT_SIZE,
- .y = g_size.h / (f32)MAX_FONT_SIZE,
- };
-
- rpb->charmap[idx + 0] = depth_idx;
- rpb->charmap[idx + 1] = depth_idx;
-
- CellStyle cs = c.style;
-
- u32 attr = (cs.attr & ATTR_SHADER_MASK) >> 2;
- u32 fg = (cs.fg.rgba & 0xFFFFFF00) | attr;
- u32 bg = (cs.bg.rgba & 0xFFFFFF00) | attr;
- u32 rmask = (gl->mode & WIN_MODE_REVERSE)? REVERSE_VIDEO_MASK : 0;
-
- rpb->texcolours[idx + 0].x = fg ^ rmask;
- rpb->texcolours[idx + 0].y = bg ^ rmask;
- rpb->texcolours[idx + 1].x = fg ^ rmask;
- rpb->texcolours[idx + 1].y = bg ^ rmask;
- END_TIMED_BLOCK();
-}
-
-static void
-push_cell_row(RenderPushBuffer *rpb, GLCtx *gl, FontAtlas *fa, Arena a, Cell *row, u32 len,
- b32 inverse, Rect cr)
-{
- ASSERT(inverse == 0 || inverse == 1);
- v2 cs = cr.size;
- v2 csw = {.w = cs.w * 2, .h = cs.h};
- for (u32 c = 0; c < len; c++) {
- Cell cell = row[c];
- if (cell.style.attr & ATTR_WDUMMY)
- continue;
- if (cell.style.attr & ATTR_WIDE) cr.size = csw;
- else cr.size = cs;
- cell.style.attr ^= inverse * ATTR_INVERSE;
- push_cell(rpb, gl, fa, a, cell, cr);
- cr.pos.x += cr.size.w;
- }
-}
-
+/* TODO: this is outdated */
/* NOTE: In this program we render to an offscreen render target that is later drawn
* to the screen as a full window quad. Therefore render_framebuffer must take care
* to handle all necessary padding (window and cell). Outside of here everyone should
* simply care about the terminal in terms of rows and columns (t->size). */
static void
-render_framebuffer(Term *t, RenderPushBuffer *rpb)
+render_framebuffer(Term *t, RenderCell *render_buf)
{
BEGIN_TIMED_BLOCK();
- v2 tl = get_terminal_top_left(t);
- v2 cs = get_cell_size(&t->fa);
- Rect cr = {.pos = {.x = tl.x, .y = tl.y - cs.h}, .size = cs};
-
TermView *tv = t->views + t->view_idx;
+
/* NOTE: draw whole framebuffer */
- for (u32 r = 0; r < t->size.h; r++) {
- push_cell_row(rpb, &t->gl, &t->fa, t->arena_for_frame, tv->fb.rows[r], t->size.w, 0, cr);
- cr.pos.y -= cs.h;
+ for (u32 row = 0; row < t->size.h; row++) {
+ for (u32 col = 0; col < t->size.w; col++) {
+ Cell *c = &tv->fb.rows[row][col];
+ RenderCell *rc = render_buf + (row * t->size.w + col);
+
+ u32 tiles;
+ rc->gpu_glyph = get_gpu_glyph_index(t->arena_for_frame, &t->gl, &t->fa,
+ c->cp, c->style.attr & FS_MASK, &tiles);
+
+ u32 attr = (c->style.attr & ATTR_SHADER_MASK) >> 2;
+ u32 rmask = (t->gl.mode & WIN_MODE_REVERSE)? REVERSE_VIDEO_MASK : 0;
+ rc->fg = ((c->style.fg.rgba & 0xFFFFFF00) | attr) ^ rmask;
+ rc->bg = ((c->style.bg.rgba & 0xFFFFFF00) | attr) ^ rmask;
+
+ /* TODO: there is probably a better way to do this */
+ if (tiles > 1) {
+ for (u32 i = 1; i < tiles; i++) {
+ rc[i].gpu_glyph = rc->gpu_glyph + i;
+ rc[i].fg = rc->fg;
+ rc[i].bg = rc->bg;
+ }
+ col += tiles - 1;
+ }
+ }
}
/* NOTE: draw selection if active */
- /* TODO: combine with original push_cell? */
if (is_valid_range(t->selection.range)) {
Range sel = t->selection.range;
iv2 curs = sel.start;
iv2 end = sel.end;
- cr.pos = (v2){.x = tl.x + cs.w * curs.x, .y = tl.h - cs.h * (curs.y + 1)};
/* NOTE: do full rows first */
for (; curs.y < end.y; curs.y++) {
- u32 len = t->size.w - curs.x - 1;
- push_cell_row(rpb, &t->gl, &t->fa, t->arena_for_frame,
- tv->fb.rows[curs.y] + curs.x, len, 1, cr);
- curs.x = 0;
- cr.pos.x = tl.x;
- cr.pos.y -= cs.h;
+ for (u32 i = curs.x; i < t->size.w; i++) {
+ Cell *c = &tv->fb.rows[curs.y][i];
+ RenderCell *rc = render_buf + curs.y * t->size.w + i;
+ rc->fg ^= (ATTR_INVERSE >> 2);
+ if (c->style.attr & ATTR_WIDE) {
+ for (u32 j = 1; c[j].style.attr & ATTR_WDUMMY; j++) {
+ rc[j].fg ^= (ATTR_INVERSE >> 2);
+ i++;
+ }
+ }
+ }
+ curs.x = 0;
}
/* NOTE: do the last row */
- push_cell_row(rpb, &t->gl, &t->fa, t->arena_for_frame, tv->fb.rows[curs.y] + curs.x,
- end.x - curs.x + 1, 1, cr);
+ for (u32 i = curs.x; i <= end.x; i++) {
+ Cell *c = &tv->fb.rows[curs.y][i];
+ RenderCell *rc = render_buf + curs.y * t->size.w + i;
+ rc->fg ^= (ATTR_INVERSE >> 2);
+ if (c->style.attr & ATTR_WIDE) {
+ for (u32 j = 1; c[j].style.attr & ATTR_WDUMMY; j++) {
+ rc[j].fg ^= (ATTR_INVERSE >> 2);
+ i++;
+ }
+ }
+ }
}
/* NOTE: draw cursor */
if (!(t->gl.mode & WIN_MODE_HIDECURSOR) && t->scroll_offset == 0) {
- iv2 curs = t->cursor.pos;
- cr.pos = (v2){.x = tl.x + cs.w * curs.x, .y = tl.h - cs.h * (curs.y + 1)};
- Cell cursor = tv->fb.rows[t->cursor.pos.y][t->cursor.pos.x];
-
- ASSERT(!(cursor.style.attr & ATTR_WDUMMY));
- if (cursor.style.attr & ATTR_WIDE)
- cr.size.w *= 2;
- cursor.style.attr ^= ATTR_INVERSE;
+ iv2 curs = t->cursor.pos;
+ Cell *c = &tv->fb.rows[curs.y][curs.x];
+ RenderCell *rc = render_buf + curs.y * t->size.w + curs.x;
+ ASSERT(!(c->style.attr & ATTR_WDUMMY));
+
+ rc->fg ^= (ATTR_INVERSE >> 2);
if ((t->mode & TM_ALTSCREEN) == 0)
- cursor.style.attr |= ATTR_BLINK;
- push_cell(rpb, &t->gl, &t->fa, t->arena_for_frame, cursor, cr);
+ rc->fg |= (ATTR_BLINK >> 2);
+
+ if (c->style.attr & ATTR_WIDE) {
+ for (u32 j = 1; c[j].style.attr & ATTR_WDUMMY; j++) {
+ rc[j].fg ^= (ATTR_INVERSE >> 2);
+ if ((t->mode & TM_ALTSCREEN) == 0)
+ rc[j].fg |= (ATTR_BLINK >> 2);
+ }
+ }
}
END_TIMED_BLOCK();
@@ -799,28 +768,35 @@ do_terminal(Term *t, f32 dt)
update_selection(t);
+ u32 cell_count = t->size.h * t->size.w;
/* NOTE: this must be done every frame since we have time varying parameters */
- RenderPushBuffer *rpb = alloc(&t->arena_for_frame, RenderPushBuffer, 1);
+ RenderCell *render_buf = alloc(&t->arena_for_frame, RenderCell, cell_count);
+ render_framebuffer(t, render_buf);
+
+ ShaderParameters *sp = &t->gl.shader_parameters;
+ sp->blink_parameter += 2 * PI * g_blink_speed * dt_for_frame;
+ if (sp->blink_parameter > 2 * PI) sp->blink_parameter -= 2 * PI;
+ sp->strike_min = (u32)(t->fa.info.baseline + 0.40 * t->fa.info.h);
+ sp->strike_max = (u32)(t->fa.info.baseline + 0.48 * t->fa.info.h);
+ sp->underline_min = (u32)(0.94 * t->fa.info.h);
+ sp->underline_max = t->fa.info.h;
+
glUseProgram(t->gl.programs[SHADER_RENDER]);
glBindFramebuffer(GL_FRAMEBUFFER, t->gl.fb);
- glUniform1i(t->gl.render.texslot, 0);
clear_colour(t->gl.mode & WIN_MODE_REVERSE);
- /* TODO: turns instead of PI nonsense */
- ShaderParameters *sp = &t->gl.shader_parameters;
- sp->blink_parameter += 2 * PI * g_blink_speed * dt_for_frame;
- if (sp->blink_parameter > 2 * PI) sp->blink_parameter -= 2 * PI;
+ glUniform2fv(t->gl.render.vertscale, 1, t->gl.window_size.E);
glBindBuffer(GL_UNIFORM_BUFFER, t->gl.render_shader_ubo);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, t->gl.render_shader_ubo);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(*sp), sp);
- render_framebuffer(t, rpb);
- flush_render_push_buffer(rpb, &t->gl);
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, t->gl.render_shader_ssbo);
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, t->gl.render_shader_ssbo);
+ glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, cell_count * sizeof(*render_buf), render_buf);
- draw_debug_overlay(t, rpb);
- flush_render_push_buffer(rpb, &t->gl);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
static f32 param = 0;
static f32 p_scale = 1;
@@ -843,6 +819,7 @@ do_terminal(Term *t, f32 dt)
#ifdef _DEBUG
DebugRecord debug_records[__COUNTER__];
+#if 0
static void
draw_debug_overlay(Term *t, RenderPushBuffer *rpb)
{
@@ -937,3 +914,4 @@ draw_debug_overlay(Term *t, RenderPushBuffer *rpb)
r.size.h = ws.h - r.pos.y;
}
#endif
+#endif