Polishing X with Glamor Keith Packard HP keithp@keithp.com
Glamor, KMS and X Delivering on the promise from 2004: Getting X Off the Hardware (OLS, 2004) 2D Drawing with GL Hardware-independent X drivers Developing X with Xephyr
Glamor: GL-based X acceleration Started by Eric Anholt in 2008 Original target was Mesa from that era GL support in Mesa is far more modern today
GL in one slide Vertex shaders Compute destination and texture coords Hardware Interpolate coords across primitive Fragment shader Fetch texture and other data Compute destination pixel value operand Composite/raster op to destination
X Core Rendering Geometry Spans, Rectangles, Text, Thin Lines Arcs, Wide Lines, Filled Arcs Polygons converted to spans Fill Style Solid, tiled, stippled Raster Op Bit-wise operations. Irrelevant today. Plane Mask Used for colormap tricks. Irrelevant today. Dash patterns For lines and arcs
Glamor last year A few fixed GLSL programs Coordinates computed with CPU Tile/stipples repeated on CPU Quite a few fallback cases Not great performance
My Glamor Plan Move computation to GPU Deliver raw X coordinates No fallbacks Template GLSL construction
Constructing GLSL Programs 'facet's declarations code uniforms Vertex and Fragment templates to glue facets together Geometry primitive facet Fill style facet Built on-the-fly as needed
Rectangle Facet static const glamor_facet glamor_facet_polyfillrect_130 = { .name = "poly_fill_rect", .version = 130, .vs_vars = "attribute vec4 primitive;\n", .vs_exec = (" vec2 pos = primitive.zw * vec2(gl_VertexID&1,” “(gl_VertexID&2)>>1);\n" GLAMOR_POS(gl_Position, (primitive.xy + pos))), };
Solid Fill Facet const glamor_facet glamor_fill_solid = { .name = "solid", .fs_exec = " gl_FragColor = fg;\n", .locations = glamor_program_location_fg, .use = use_solid, };
Solid Rectangle Vertex Shader #version 130 attribute vec4 primitive; uniform vec4 v_matrix; void main() { vec2 pos = primitive.zw *vec2(gl_VertexID&1, (gl_VertexID&2)>>1); gl_Position.xy = (primitive.xy + pos).xy * v_matrix.xz + v_matrix.yw; gl_Position.zw = vec2(0.0,1.0); }
Solid Rectangle Fragment Shader #version 130 #ifdef GL_ES precision mediump float; #endif uniform vec4 fg; void main() { gl_FragColor = fg; }
Core X Text Indexed by character ASCII, ISO-Latin 1, Shift-JIS 8 or 16 bits 16 bits are either “2d” or “1d” Bitmap per glyph Glamor stores entire font in one texture 8 bits per pixel to save space Fragment shader fetches bits with shift/mask
Line Dashing GL supports only a few fixed dash pattern X supports huge dash patterns Unlimited list of on/off lengths Glamor stores dash list in texture 0xff for 'on' pixel, 0x00 for 'off' pixel Vertex shader computes correct interpolation Checks for X major vs Y major lines Interpolates dash coordinate along major axis Dash offset computed for each segment by CPU Fragment shader fetches dash value
Glamor Core Accelerated Operations Filled Rectangles Filled Spans Copy Area Copy Plane (n to n) Points Thin lines (solid and dashed) Text
Interesting Results Solid/tiled/stippled all run at the same speed Glamor accelerates “weird” operations trivially, like stippled text (which was used in Motif years ago) GLSL is way nicer than GPU Assembly
Lessons from x11perf Large batched operations are awesome rectangles lines text Small operations are dominated by GL library window configuration polygons
Potential performance ideas Batch operations across X requests Leave operations pending until flush Check previous queued operation Fewer uniforms, more vertex attributes Solid colors
Render Extension Render added to X in 2000 Anti-aliased text was the motivator Conflicting goals: Satisfy 2D application requirements Perform well on existing hardware Exposed best to apps with cairo
Render Overview
Render Objects Sources Images. Regular X pixmaps. Gradients. Smooth gradations between colors. Solid colors. Solid colors. Masks Any source, but use only the alpha value Geometry (trapezoids, triangles, rectangles) Glyphs (special storage for image masks)
Render Operations Composite Paint a single rectangle Glyphs Paint multiple rectangles as described by a sequence of glyph masks Trapezoid/triangle Construct a mask from a set of polygons Paint a single bounding rectangle using that mask and a single source
Render Glyphs Client constructs “glyph sets” Contain a set of alpha masks, one per glyph Each glyph also has spacing information Generally one glyph set per face Arbitrary indices; no semantic value Draw a list of glyphs from one or more sets
Glamor Glyph Storage Glyph sets are often larger than max texture size Applications often draw glyphs from multiple glyph sets in one operation Glamor uses glyph-set independent “caches” Append-only on miss Flush drawing operation and allocate new cache when full Avoids complex 2D allocation Better cache space utilization Avoids stalling GPU on miss Never replacing existing glyph with new glyph
Drawing Glyphs For each glyph Ensure glyph is in cache Append glyph info to vertex list Flush vertex list when cache is full or done drawing.
Future Render Work Got side-tracked by GSoC failure Figure out Render source management Fragment shader gradient computation Image sources, including repeat modes Add composite code Simple, once source operands works. Hardware trapezoids?
Measuring X Performance x11perf is not representative of real applications We used to have cairo traces Those are fairly stale, and draw only off-screen now We have gtkperf. It shows only old gtk+ widget-based performance and core graphics. Few (no?) “real” applications provide any benchmarking mode For GL, many games provide useful benchmark data internally
GL vs X. Sometimes it's not great Texture formats vs X pixmaps and pictures GLES limitations Older hardware
GL textures vs X pixmaps X pixmaps define only depth Color data defined only in relation to other objects Core X drawing has no color meaning Purely pixel values Render pictures are one usage Picture format defines pixel format Can create multiple Pictures per Pixmap gtk+ actually does this GL Textures format defined by data Store texture data and you have a format
Glamor fails at this today GL format approximated by remembering last Render format Kludges for multiple pictures using different formats in one operation (as Gtk+ does) Reformat texture when switching formats This is expensive and wrong
Need ARB_texture_view extension Requires ARB_texture_storage Allows multiple textures from one bag of pixels Separation looks much like picture/pixmap Supported on most hardware Fallback by fetching/storing data to temporary or new pixmaps.
GLES2 limitations GLES2 is popular on embedded GPUs Like VC4 Missing lots of stuff Glamor uses today GL_QUADS 32-bit integers instanced drawing texture pack/unpack formats logic ops
Older Hardware and Glamor To be specific: i915 and i945 Hardware lacks vertex shaders executed on CPU Mesa version is interpreted and slow Glamor performance is pretty bad here Options: Fix Mesa. LLVM vertex shaders on CPU? Special case glamor shaders in Mesa with custom code? Use existing xfree86 video drivers? Construct new drawing-only driver interface?
One driver to rule them all. KMS + GBM + Glamor = X Modesetting driver Merged into the X server code base for 1.17 Track API/ABI changes easily Uses Glamor where GL is available Uses software rendering otherwise
Modesetting feature support DRI2 Mesa, VaAPI DRI3/Present Missing page flipping in 1.17 Xv Only textured video for 1.17 RandR Including shadow buffers for rotation
Modesetting saves a bit of code intel 272313 ati 63131 nouveau 32791 Total 368235 modesetting 5032
Modesetting Plans Add page flipping Code should be ready shortly Fix shadow support Conflict between “regular” shadowing and RandR shadows Just force RandR shadowing on when “regular” shadows are requested.
Xephyr: Single Machine X Development Nested X server Used to be software only Now includes Glamor support Allows lots of Glamor debugging without restarting main X server Vastly simplified GDB experience
X 1.17 and 1.18 1.17 contains: First integrated modesetting driver Improved core X glamor code For 1.18, we'll add Page flipping and better shadows for modesetting At least new glyphs for glamor GLES support could be fixed with some effort