Bug 1359

Summary: TextRenderer glyphs sometimes become garbled because LevelSet.compactAndAdd doesn't tell GlyphCache to update texcoords
Product: [JogAmp] Jogl Reporter: Andy Edwards <jedwards>
Component: utilAssignee: Sven Gothel <sgothel>
Status: UNCONFIRMED ---    
Severity: normal    
Priority: P4    
Version: tbd   
Hardware: All   
OS: all   
Type: DEFECT SCM Refs:
Workaround: ---

Description Andy Edwards 2019-01-28 20:08:43 CET
Every once in awhile, the text I draw with TextRenderer suddenly becomes garbled, with either the wrong glyph showing in place of another one, or fragments of multiple glyphs drawn within the texcoord bounds of a glyph.

After extensive debugging I noticed the following in RectanglePacker.add:

    do {
      // Try to allocate
      if (levels.add(rect))
        return;

      if (manager.canCompact()) {
        // Try to allocate with horizontal compaction
        if (levels.compactAndAdd(rect, backingStore, manager))
          return;
        // Let the manager have a chance at potentially evicting some entries
        tryAgain = manager.preExpand(rect, attemptNumber++);
      } else {
        tryAgain = manager.additionFailed(rect, attemptNumber++);
      }
    } while (tryAgain);

The call to levels.compactAndAdd doesn't fire any events to tell the GlyphCache to update texcoords for its glyphs, so after horizontal compaction, GlyphCache will have bad texcoords and draw garbled text to the screen.

By contast, manager.preExpand fires a REALLOCATE event, which GlyphCache responds to by  clearing the cached texcoords so they will be recomputed, and manager.additionFailed fires a FAILURE event, which GlyphCache responds to by clearing the entire cache.

Personally, I think the amount of GlyphCache/TextureBackingStoreManager/RectanglePacker is just asking for bugs to happen.  In my own app I solved the issue by eradicating all compaction code from RectanglePacker; any time the glyph texture fills up, I just flush  the glyph texture and glyph quads to the GPU, then clear the cache and start over with a blank texture (using the next larger size if maxSize hasn't been reached).  It may not be quite as efficient but I'm 10 times more confident that it works correctly (and also works when so many different glyphs need to be drawn that not even the maximum texture size can fit all of them).