All presentation display drivers have two major but only marginally related functions: drawing to the display, and drawing to memory bit maps. This dual-mode drawing architecture was resolved by having the bit-map drawing code emulate the XGA hardware. Thus, all of the code needed to set up a drawing operation would be almost identical for the display and for bit maps. Hard-draw mode, therefore, is the mode in which the driver will write data to the XGA adapter, while Soft-draw mode writes only to system-memory bit maps.
Note: The bit map drawing code in the XGA driver emulates a subset of the XGA's hardware drawing capabilities.
In the previous example, Hard-draw mode was used. The following is an example of Soft-draw mode from the EDDNBBLT.C file.
if (AIxfer.pbmhDest == &DirectListEntry) { SetDrawModeHard; } else { SetDrawModeSoft; }
This example is from the eddt_CacheCharacter() function in the EDDNGCHS.C file in the glyph-caching code.
ShadowXGARegs.FgMix = HWMIX_SOURCE; ShadowXGARegs.BgMix = HWMIX_SOURCE; ShadowXGARegs.ColCompCond = COLCOMP_ALWAYS; /**************************************************************/ /* Set up destination pixmap details. */ /**************************************************************/ ShadowXGARegs.pixmapBaseA = pVRAMCacheStart + offNextFree11Pos; ShadowXGARegs.pixmapWidthA = xGlyphWidthHW; ShadowXGARegs.pixmapHeightA = yGlyphHeight; ShadowXGARegs.pixmapFormatA = ONE_BPP; /**************************************************************/ /* Set up source pixmap details. */ /**************************************************************/ ShadowXGARegs.pixmapBaseB = pSysCacheStartPhy + offNextFree11Pos; ShadowXGARegs.pixmapWidthB = xGlyphWidthHW; ShadowXGARegs.pixmapHeightB = yGlyphHeight; ShadowXGARegs.pixmapFormatB = ONE_BPP | MOTOROLA; /**************************************************************/ /* Set up blt details - we want to copy the whole character. */ /**************************************************************/ ShadowXGARegs.SrcXAddr = ShadowXGARegs.SrcYAddr = ShadowXGARegs.DstXAddr = ShadowXGARegs.DstYAddr = 0; ShadowXGARegs.OpDim1 = xGlyphWidthHW; ShadowXGARegs.OpDim2 = yGlyphHeight; /**************************************************************/ /* Set up the pixel_op to do the blt. */ /**************************************************************/ ShadowXGARegs.PixOp = BACK_SRC_SRC_PIX_MAP | FORE_SRC_SRC_PIX_MAP | STEP_PXBLT | SRC_PIX_MAP_B | DST_PIX_MAP_A | PAT_PIX_MAP_FORE | MASK_PIX_MAP_OFF | DRAW_MODE_DONTCARE | DIR_OCTANT_LRTB; /**************************************************************/ /* Now do the blt. We have to use the hardware to do this. */ /* Set softDrawInUse to false, and then restore it after the */ /* blt has been completed. (Higher level functions may be in */ /* software-drawing mode, but still keep the VRAM-cache */ /* copy up-to-date.) */ /**************************************************************/ tempDrawMode = softDrawInUse; softDrawInUse = FALSE; TransferShadowRegisters( TSR_MAP_A | TSR_MAP_B | TSR_COLOUR_MIX | TSR_COORDINATES | TSR_PIXELOP ); softDrawInUse = tempDrawMode;
The preceeding code example copies a character from system memory into the VRAM in cache of the XGA presentation display driver. The TransferShadowRegisters function initiates an XGA bus-mastering BitBlt to copy the character.
The top-level functions in the XGA presentation display driver are written in C language. These functions are set up for a drawing operation by parsing through data structures passed in from GRE and setting up the ShadowXGARegs structure. At a certain point, they look at the address of the bit map that was passed in by GRE. If the address is the display, it uses the SetDrawModeHard macro, otherwise, SetDrawModeSoft is called. In the above example, SetDrawModeHard is executed rather than SetDrawModeSoft. The SetDrawModeHard and SetDrawModeSoft macros, which are located in the EDDMACRO.H. file, are described in the following example:
#define SetDrawModeSoft \ { \ if (!softDrawInUse) \ { \ pXGARegs = (pMMReg)&ShadowXGARegs; \ LinePatternCur = LinePatternSys; \ MarkerCur = MarkerSys; \ pDrawFunctions = (pDrawFunctionsTable)softDrawTable; \ softDrawInUse = TRUE; \ } \ } \ \ #define SetDrawModeHard \ { \ if (softDrawInUse && foregroundSession) \ { \ pXGARegs = pRealXGARegs; \ LinePatternCur = LinePatternPhys; \ MarkerCur = MarkerPhys; \ pDrawFunctions = (pDrawFunctionsTable)hardDrawTable; \ softDrawInUse = FALSE; \ } \ }
Initially, SetDrawModeHard determines that it is currently in software-drawing mode by looking at the global flag softDrawInUse and by ensuring the presentation display driver is in the foreground. (A BitBlt operation does not occur in the XGA hardware while the user is running a DOS text-mode application in the foreground.) Next, SetDrawModeHard points pXGARegs to the selector and offset of the XGA driver's memory-mapped registers. (PXGARegs is a pointer used by various assembler-language modules.) It then sets up pointers to the line patterns and markers in XGA video memory. Finally, it sets up the pDrawFunctions table to point to the set of assembler-language functions that draw to the XGA display, and clears the softDrawInUse flag.
Very few XGA drawing operations are initiated by the C code in the XGA driver. Instead, a group of assembler-language functions (pDrawFunctions) are called and they complete all of the real drawing work. These functions are:
eddh_DestOnlyBlt
eddh_DrawText
eddh_PatDestBlt
eddh_PMIMAGEDATA
eddh_PMLINES
eddh_PMPLOTSTEP
eddh_PMSCANLINE
eddh_SrcDestBlt
eddf_DestOnlyBlt
eddf_DrawText
eddf_PatDestBlt
eddf_PMIMAGEDATA
eddf_PMLINES
eddf_PMPLOTSTEP
eddf_PMSCANLINE
eddf_PMSHORTLINES
eddf_SrcDestBlt
These functions fall into two groups: one for drawing to the display, and one for drawing to memory. Pointers to these functions are stored in two tables in the EDDFDADA.C file. The hardDrawTable contains pointers to the functions that start with "eddh." The softDrawTable contains pointers to the functions that start with "eddf."
These functions are important as they represent the bulk of the hardware-dependent code in the driver. The following is a listing of the source files associated with each function:
EDDHBBLT.ASM: eddh_DestOnlyBlt eddh_PatDestBlt eddh_SrcDestBlt eddf_DestOnlyBlt eddf_PatDestBlt eddf_SrcDestBlt EDDHGCHS.ASM: eddh_DrawText eddf_DrawText EDDHIMAG.ASM: eddh_PMIMAGEDATA eddf_PMIMAGEDATA EDDHLINE.ASM: eddh_PMLINES eddh_PMPLOTSTEP eddf_PMLINES eddf_PMPLOTSTEP EDDHSCAN.ASM: eddh_PMSCANLINE eddf_PMSCANLINE EDDHSHRT.ASM: eddh_PMSHORTLINES eddf_PMSHORTLINES
Note that each file lists two versions of each routine: one for hardware drawing, and the other for drawing to bit maps. The code for soft-draw and hard-draw is similar in all of these files. Each of these files is assembled twice, once with HARD_DRAW defined, and once with SOFT_DRAW defined. The conditional assembler in the files renames the major functions, and inserts calls to the bit-map drawing routine, EDDF_MESS. (EDDF_MESS is located in the DDFFAST.ASM file.) The remainder of the differences are hidden in the memregread and memregwrite assembler macros. In soft-draw mode, memregread and memregwrite write to the ShadowXGARegs structure. The pointer used by memregread and memregwrite is set up in the movxga macro, which gets the pointer to the registers from pMemReg. (pMemReg is set to point to the ShadowXGARegs structure by the SetDrawModeSoft C macro.) The following is an example from the EDDHBBLT.ASM file, from the start of the function SrcDestBlt (SrcDestBlt is changed by way of conditional assembler to eddh_SrcDestBlt or eddf_SrcDestBlt, depending on whether the module is built for hard-draw mode, or for soft-draw mode.):
pushxga ; get the base address of the hardware registers movxga pXGARegs ; use ebx as a pointer to the destination bit map header mov ebx, AIxfer.pbmhDest ; use edi to count the number of clip regions movzx edi, word ptr AIxfer.cDestClipRects ; select the destination map memregwrite pi_map_index_A, SEL_PIX_MAP_A
In hard-draw mode, pMemReg points to the XGA registers. Most of the other conditional assembler controls minor differences between hardware and software-drawing modes (for example, not waiting for completion of the previous hardware-drawing operation in software-drawing mode).
None of the assembler-language drawing functions are directly called by the XGA driver's C-code functions; they are always called through the pDrawFunctions table. Again, this usually allows the same code to process the setup for either the display or bit-map drawing operations. In the glyph-caching code example, the state of the softDrawInUse flag is preserved, set to FALSE, and then restored. The call to TransferShadowRegisters initiates a BitBlt to copy the glyph into VRAM. TransferShadowRegisters only touches the hardware if the driver is in hard-draw mode, that is, if softDrawInUse is FALSE. The character-caching code maintains identical caches in system memory and off-screen VRAM. Because the bit-map version of the text-drawing code calls the eddt_CacheCharacter() routine (the routine shown in the glyph-caching code example), there will be cases in which the eddt_CacheCharacter routine needs to use the hardware to copy the glyph to VRAM, even though it is in soft-draw mode.
In other words, high-level functions in the driver that are in C language, such as eddb_BitBlt(), set the mode for hard-draw mode or soft-draw mode and then call lower level C functions such as PixBltThroughClips(). These functions are relatively generic. Setup values in the ShadowXGARegs structure can be used to initialize the XGA chip set, or they can be used to interpret a bit-map drawing by the eddf_MESS() file.
PixBltThroughClips() (and other level C functions) conducts slightly more setup, calls the TransferShadowRegisters structure, and then calls one of the assembler-language worker functions by way of the pDrawFunctions table. The assembler-language drawing routines are assembled for either hardware drawing or software drawing. The software drawing versions call eddf_MESS() to draw to bit maps, while the hardware-drawing versions write to the XGA command register, which initiates a drawing operation.