The XGA presentation display driver caches bit maps, fonts, line-patterns, markers, and dithered patterns for BitBlt in off-screen VRAM. Off-screen VRAM allocation is divided between two files, namely EDDEVRAM.C and EDDNCACH.C. The EDDEVRAM.C file stores various patterns and markers into off-screen memory. The EDDNCACH.C file contains the code for maintaining the font and bit-map caches.
The XGA presentation driver is able to cache small bit maps in off-screen VRAM. It limits the size of these bit maps to 1600 bytes (refer to EDDNCACH.H), which is large enough for a 40 x 40 pel icon at 8 bits-per-pel, but not large enough for a 32 x 32 pel icon at 16 bits-per-pel. After the XGA presentation display driver reserves off-screen video memory for the software cursor, the font cache, patterns, and so forth, it uses what remains for caching small bit maps. The bit map cache is created by the initialise_bm_cache() function. This cache takes the remaining off-screen VRAM, divides it into 1600-byte chunks, and creates an array of structures of type BMCACHE with that number (the remaining off-screen VRAM divided by 1600) of elements. Bit maps either fit in the cache, or they do not fit in the cache. If they fit in the cache, they take the entire 1600 bytes of cache. For example, a 32 x 32 monochrome bit map, if cached, occupies a 1600 byte slot in the cache even though it is only 128 bytes. The only variable is the number of bit maps that may be cached, and that number is determined at system startup.
The following bit maps are cached in PixBltThroughClipsViaPhunk() (PIXBLT.C):
if ( !fSeamlessActive && !AIxfer.fStretching && /* <DCRTURBO> */ (AIxfer.pbmhSrc->BMPhys == NULL) && (AIxfer.pbmhDest->bit map == NULL) && (ShadowXGARegs.ColCompCond != COLCOMP_SRC_NOT_EQUAL) && !UsePaletteMapping && AIxfer.pbmhSrc != &DrawBitsBMHeader ) { if ( AIxfer.pbmhSrc->BMSize <= VRAM_BM_CACHE_SIZE ) { if ( cache_bit map(AIxfer.pbmhSrc) ) { //Caching the bit map may have corrupted some of our Color and Mix //Registers. Restore them before calling PixBltThroughClips(). TransferShadowRegisters( TSR_COLOUR_MIX ); PixBltThroughClips(); return; } } }
If cache_bitmap() is able to cache the bit map, PixBltThroughClipsViaPhunk() can call PixBltThroughClips because both the source and destination for the BitBlt are in video memory. PixBltThroughClips enumerates through the clipping rectangles (if any), and performs a screen-to-screen BitBlt.
Cache_bit map() always returns TRUE. Cache_bit map does not check the size of the bit map, which is why the code in the previous figure looks for an empty slot in the cache. If it is unable to find one, it calls evicted_cache_slot(), which deletes a bit map out of the cache. The following is code for evicted_cache_slot():
ULONG evicted_cache_slot(VOID) /**********************************************************************/ /* Evicts a bit map from the cache and returns its slot number for */ /* use by a new bit map. */ /* */ /**********************************************************************/ { evict_cached_bit map(next_eviction); if ( next_eviction == 0 ) { next_eviction = max_cached_bit maps - 1; return(0); } else { return(next_eviction--); } } /* evicted_cache_slot */
The eviction scheme uses round-robinschedulingwhenevictingbitmapsfromthecache . Itispossiblethatthebitmapevictedwillbetheonejustallocatedonthepreviouscall . Thiscouldleadtoacertainamountofcachethrashing .
The font cache packs glyphs together in the font cache, rather than creating a fixed number of fixed-size slots for glyphs. Instead, there are a maximum of 10 fonts that may be cached. At initialization time, an array of FONTCACHEINFO structures is allocated in CreateFontCache() (in the EDDNCACH.C file). FONTCACHEINFO is defined in EDDTYPET.H, and is as follows:
/*********************************************************************/ /* Type definition for FontCacheInfo */ /**********************************************************************/ #define MAX_NUM_CODEPOINTS 256 typedef struct _FONTCACHEINFO { /* fci */ FOCAMETRICS fmFontMetrics; USHORT usHashMetrics; USHORT usUsageCount; USHORT usFontID; USHORT usCodePage; ULONG aulCachedCharOffset[MAX_NUM_CODEPOINTS]; #ifdef FULL_ADDRESS PVOID apCharDef[MAX_NUM_CODEPOINTS]; #else /* ndef FULL_ADDRESS */ USHORT apCharDef[MAX_NUM_CODEPOINTS]; #endif /* ndef FULL_ADDRESS */ /**********************************************************************/ /* Defect 75206. 800 x 600 x 16bit in 1MB VRAM does not leave enough */ /* room to cache large AVio fonts in one plane. For this resolution, */ /* reduce the number of cached fonts to 8 and allow them to wrap */ /* (once) to plane index + 8. For each character, ausPlaneOffset is */ /* set to: */ /* 0 - in plane 0 through 7 */ /* 1 - in plane 8 through 15 */ /* -1 - not in 16-bit color, ignore */ /**********************************************************************/ #ifdef _8514 USHORT ausPlaneOffset[MAX_NUM_CODEPOINTS]; #endif } FONTCACHEINFO; typedef FONTCACHEINFO * PFONTCACHEINFO;
As the driver draws text strings, it determines if the font is already in the cache. If not, it takes an entry out of the array of FONTCACHEINFO structures. It then checks each character in the string to be drawn, and if they are not cached (the entry in the aulCachedCharOffset array for that codepoint is NULL), it puts each character for the string into the cache. If the 64KB cache overflows, the entire cache is flushed, and all of the characters for the string are cached. The details of this process are in the EDDNGCGS.C, EDDHGCHS.ASM, and EDDNCACH.C files.