diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2011-04-28 08:51:20 -0400 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2012-05-28 13:26:19 -0400 |
commit | 737b4564356196f2c922b197cad7d334633c34b9 (patch) | |
tree | 259a9e75e3a311b387ec11dfad55c50566aa777e | |
parent | 13ad1c51e49674b59ec7defa9975cf9b4c1f6743 (diff) |
Add glyphs.txt
glyphs.txt
-rw-r--r-- | glyphs.txt | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/glyphs.txt b/glyphs.txt new file mode 100644 index 00000000..ec7c531f --- /dev/null +++ b/glyphs.txt @@ -0,0 +1,338 @@ +TODO: + - uploading glyphs should be done through pixman images + - this is convenient for both cairo and X. And in fact + easier within pixman as well. + + - bearing/advance probably needs to be computed outside of + pixman. Alternatively, there should be the possibility of + including offsets within the list of glyphs. + + +New approach: + +Pixman has the concept of a glyph cache, and not the concept of a +glyph set. + +API: + +pixman_glyph_cache_freeze(); +pixman_glyph_cache_thaw(); +bool pixman_glyph_cache_contains(cache, void *font, uint32_t index); +void pixman_glyph_cache_insert(cache, void *font, uint32_t index, + format, x, y, data, ...); +struct command +{ + union + { + struct + { + void *font; + } switch; + + struct + { + int x, y; + } displace; + + struct + { + uint32_t n_glyphs; + } glyphs; + } u; +}; + +pixman_glyph_commands_t *pixman_glyph_commands_begin (void *data, int n_bytes); + +pixman_glyph_commands_t *pixman_glyph_commands_switch (void *data, void *font); +... *pixman_glyph_commands_displace (void *data, int x, int y); +... *pixman_glyph_commands_glyphs (void *data, uint32_t n_glyphs, + uint32_t *indices); + +void *pixman_glyph_commands_end (void *data); +void pixman_glyph_commands_free (void *data); + + +void pixman_composite_glyphs(..., src, cache, commands, dst); + +To use it, you would do: + + uint8_t data[1024]; + uint32_t glyphs[N_STACK_GLYPHS]; + uint32_t *g = glyphs; + + pixman_glyph_commands_t *commands; + + pixman_glyph_cache_freeze(); + + commands = pixman_glyph_commands_begin (data, sizeof (data)); + + for (i = 0; i < blah; ++i) + { + if (glyph) + { + if (g - glyphs == N_STACK_GLYPHS) + { + command = add_glyphs (command, font, glyphs, N_STACK_GLYPHS); + g = glyphs; + } + *g++ = index; + } + else + { + command = add_glyphs (command, font, glyphs, g - glyphs); + g = glyphs; + + if (displace) + ...; + else if (font) + ...; + } + } + + command = add_glyphs (command, font, glyphs, g - glyphs); + commands = pixman_glyph_commands_end (commands); + + pixman_composite_glyphs (src, cache, commands, dst, ...); + + pixman_glyph_commands_free (commands); + + +In the X server, do we get any notification when a glyph disappears? +Yes, we do in UnrealizeGlyph(). + +We can be even simpler than this: + +pixman_glyph_cache_freeze(); +pixman_glyph_cache_thaw(); +bool pixman_glyph_cache_contains(cache, void *font, void *index); +void pixman_glyph_cache_insert(cache, void *font, void *index, + format, x, y, data, ...); +pixman_composite_glyphs (src, + void *font, void **indices, int n_indices, + pixman_format_t mask_format, + dst, + ...); + +where the X server void use NULL for font, and the glyph pointer for +indices, and cairo would use scaled_font for font and the +glyph_indices for the indices. + +mask_format would determine the format used for the mask, although +another possibility would be to say that a8 glyphs are expanded to +shades of white. Or saying that glyphs get added with a white source. + +How do we deal with font matrices in cairo? Presumably the same way +they are dealt with in the xlib surface. + + +Glyphs in the X server + +- Glyphsets are current global and not attached to a screen and + therefore not something the driver can influence + +- In EXA, glyphs work like this: + + - There are cache pixmaps in device memory that contain + recently rendered glyphs. + + - when a set of glyph arrives to be rendered, they are looked up in + the pixmap caches; if they are not there, they are uploaded, and a + random glyph is evicted. + +Ideally, I think all glyphs would be stored contiguously in device +memory, and a primitive would be emitted per glyph with sufficient +information that each glyph could be composited. + +For software, we definitely want to store all the glyphs in one "tall" +image, possibly sorted by frequency. Or even contiguously in a big +array with varying strides. + +In either case, the driver/DDX needs to be involved in the X server. + +There is already a per-screen copy of each glyph, so it's not a +problem to make a per-screen copy of each glyph set. Besides, in a +randr world, people generally only have one screen even if they have +multiple monitors. + +Per-screen glyph sets + +- Useful for DMX as well - since there is no real reason to store the + glyphs on the dmx server. + +- Actually, the glyph handling in DMX is broken - it is sending + pointers across, not the actual bits. + +GlyphSet +{ + XID id; + RealGlyphSet real_sets[num_screens]; +}; + +CreateGlyphSet -> + GlyphSet set = malloc(); + set->id = id; + + for each screen s + glyphset[s] = screen->CreateGlyphSet(); + + FreeGlyphSet would of course call into each screen to free + the real sets. + + Maybe a "RealGlyphSet" should actually be called GlyphSet, + and the global structure should be called something else. + +AddGlyphs (set, glyphs) -> + for each screen s + s->AddGlyphs (set->real_sets[s], glyphs); + +CompositeGlyphs () -> + s = screen + walk glyph list and replace glyphset with real sets depending + on screen . + screen->CompositeGlyphs (s, glyphs); + + Or just use the existing GlyphList infrastructure + +There would mi versions of these calls of course. + +And there should perhaps be some compatibility wrapper macros type +things in place, though it probably can't be completely source +compatible. + + +(a) Change the GlyphSet structure, make it compile. + +(b) mi would have to store some private information related to the + glyph sets. + +(c) It may make sense to move most of the existing mi code into exa, + and then do something entirely different for fb. + + This does mean the uxas will have to be updated. + + + +Assumptions: + +- if you are going to composite the glyphs in software, then you will + eventually use pixman, which means it is fundamentally not + unreasonable to have the glyphs stored in a pixman data structure. + +- if you are going to composite the glyphs in hardware, then the + glyphs should still be stored somewhere in host memory because they + will be needed there anyway from time to time and migrating them out + is expensive. Currently, the glyphs in pixmaps, which may or may not + be in video memory. + +The consequence is that if we add an fbGlyphs that doesn't require +individual pictures, then it is not entirely unreasonable to construct +the glyph pictures on the fly. The open source drivers should be fine +with this - the nvidia binary driver probably not, given that Aaron +added the USAGE_GLYPH hint to CreatePixmap. + +Another possibility would be to still create the glyph pixmaps like we +do now, but have them point to the pixman data. + +A third possibility is to simply have fb create a pixman_glyph_set_t +and cache it in private data. + +Fundamentally, X should not make the assumption that the driver wants +to store the glyph in a pixmap. That is a decision that the driver +should make. + + +- Glyphs in Render have strides that are padded to 32 bits. The spec + is unclear (the *Render* spec is unclear? No way) about this, but + the code pads the stride to 32 bits. + + Well, it uses PixmapBytePad(), which is padding to 32 bits. + +- The server has a pixman_glyph_context_t. This context is global and + holds all the cached glyphs. + + Such a context can + + - be created + - be destroyd + + - privately, + - add a glyph + - remove a glyph + - has static glyph pointers that remain valid until the glyph + is removed + + - when the context is deleted, all associated glyphs are + deleted with it. + + The only public API for it is "create()" and "destroy()". It is also + passed to pixman_glyph_set_create(). + +- A pixman_glyph_set can + - be created with a reference to a context + - hold a reference to a context + - map ids to bits + - add/remove glyphs (both id based) + - map ids to bits + +Server side: + +At the moment, the glyphs are stored in Pictures, one picture (and +pixmap) per glyph. The drivers usually copy some of the glyphs into +textures and use those for hardware acceleration. + + +- There is one global glyph context + +- GlyphSet becomes something that just holds a reference a pixman + glyph set. + +- Glyph still exists pretty much as it is now. + +- GlyphUninit deletes the global context. + + + + +fb gains fbGlyphs which will issue pixman_composite_glyphs() with a +list of glyph commands. + + +Later + +Ways to get at the whole image + + +In server, GlyphSet goes away, replaced with pixman_glyph_set_t. + +Glyph still exists, it is the private pointer in the glyph set. + +- fb caches pixman images + +- fb also gains an fbGlyphs which will replace miGlyphs and + + + +GlyphSet +Add glyphs + + + + +glyph set: +- add_glyphs_unique() /* hashes */ +- add_glyphs /* doesn't hash glyph data */ +- get pointer, format, width, height, stride of big image +- get coordinates in big image for glyph +- callback when big image becomes invalid + + - instructions on the desired tiling type? + +- method to composite a bunch of glyphs + + pixman_glyph_set_composite (op, source, glyphs, dest, sx, sy, dx, dy); + + + pixman_image_composite_glyphs (op, source, dest, sx, sy, dx, dy, + + + |