aboutsummaryrefslogtreecommitdiffstats
path: root/symbols/symbols-gl.h
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-27 14:21:39 +0100
committereunhhu <[email protected]>2026-09-27 14:21:39 +0100
commit2c1e29780da41bba13ac84ad01472d550e6d02e8 (patch)
treead24387435dffc3cde5354295584136af6720f1f /symbols/symbols-gl.h
parent2920e389f624263efe515d9a5f33f6b822efff5e (diff)
downloadvega-2c1e29780da41bba13ac84ad01472d550e6d02e8.tar.gz
vega-2c1e29780da41bba13ac84ad01472d550e6d02e8.zip
Draw text from an atlas the CPU fills, composed by the GPU
Each size's symbols are drawn on the CPU into one 8-bit atlas, every pixel the exact area its curves cover, and text is a quad per glyph reading it. A 1080p page of 11,382 glyphs composes in 1.07 ms at 16 px (it took 525 ms computing coverage per fragment), and the composed pixels are the CPU raster's exactly (worst difference 0 for DejaVu's ASCII, 1 for Noto's 11,172 Hangul syllables). Computing coverage on the GPU lost on both counts: a compute pass filling the atlas took 5-13x longer than one Cortex-A76 core (35 against 2.7 ms at 16 px), and its faster sorting-network form computed whole rows wrongly under this Mesa V3D. Coverage now has one implementation, in C, and the shaders only compose. vega_symbol_raster takes a row stride to draw into the atlas in place.
Diffstat (limited to 'symbols/symbols-gl.h')
-rw-r--r--symbols/symbols-gl.h43
1 files changed, 31 insertions, 12 deletions
diff --git a/symbols/symbols-gl.h b/symbols/symbols-gl.h
index 4c6db67..919a114 100644
--- a/symbols/symbols-gl.h
+++ b/symbols/symbols-gl.h
@@ -3,22 +3,41 @@
#include "symbols.h"
#include <GLES3/gl31.h>
-/* Symbols drawn by the GPU (OpenGL ES 3.1): the file's point table goes up
- * as it is, one storage buffer, and each pixel of a symbol's box sums the
- * exact area of the curves crossing its row, as vega_coverage does. Rows
- * are cut into bands at upload, each listing its curves, so a pixel reads
- * only those. Needs a current context. */
+/* Symbols on the GPU (OpenGL ES 3.1): the symbols wanted at one scale are
+ * drawn on the CPU into an atlas, each pixel the exact area its curves cover
+ * (vega_symbol_raster), and text is quads reading it. On the Pi 5 the CPU
+ * draws the atlas faster than the GPU's compute could, and the GPU composes
+ * a 1080p page of text in about a millisecond (docs/design/002). A scale that
+ * keeps changing (a zoom) draws its atlas again. Needs a current context. */
typedef struct {
- GLuint program, points, bands, instances, array;
- GLint viewport;
+ GLuint draw, array, instances;
+ GLint target;
} VegaGl;
-/* A symbol placed: its origin in pixels from the target's top left, and
- * pixels per unit. */
-typedef struct { float x, y, scale; uint32_t symbol; } VegaGlyph;
+/* Where each symbol is in an atlas: its rectangle there (x, y, width, height)
+ * and the pixel offset of that rectangle's top left from the symbol's origin
+ * (right, up). A symbol with nothing to draw has an empty rectangle. */
+typedef struct { int32_t x, y, width, height, left, top; } VegaPlace;
-bool vega_gl_open(VegaGl *, const VegaSymbols *, char *error, size_t error_size);
+typedef struct {
+ GLuint texture; /* 8-bit coverage */
+ int width, height;
+ float scale; /* pixels per unit */
+ uint32_t symbols;
+ VegaPlace *places; /* per symbol index */
+} VegaAtlas;
+
+/* A symbol at a pen position (whole pixels from the target's top left, on the
+ * baseline). */
+typedef struct { int32_t x, y; uint32_t symbol; } VegaGlyph;
+
+bool vega_gl_open(VegaGl *, char *error, size_t error_size);
+/* Draw symbols (their indices; all when wanted is NULL) at scale into a new
+ * atlas; false when they do not fit one texture. */
+bool vega_gl_atlas(VegaGl *, const VegaSymbols *, float scale, const uint32_t *wanted, uint32_t count, VegaAtlas *out,
+ char *error, size_t error_size);
/* Coverage added into the red channel of the bound framebuffer. */
-void vega_gl_draw(VegaGl *, const VegaSymbols *, const VegaGlyph *, uint32_t count, int width, int height);
+void vega_gl_draw(VegaGl *, const VegaAtlas *, const VegaGlyph *, uint32_t count, int width, int height);
+void vega_gl_atlas_close(VegaAtlas *);
void vega_gl_close(VegaGl *);
#endif