The various S3 chips do not directly support hardware drawing of packed 24-bit-per-pel modes. Some of them include drawing engine support for 32-bit-per-pel modes, which can be found in the IBM Device Driver Source Kit for OS/2, Version 1.2; but the S3 driver does not support this mode. Instead, the S3 driver attempts to use the drawing engine where it can, and falls back to the frame buffer in situations where it is unable to use the drawing engine. All line drawing is done in software at 24-bits-per-pel. Screen-to-screen copy bitblts can be processed, but fills of any sort, including the monochrome expansion operations, can be performed only if the red, green, and blue components of the color are identical. The drawing engine treats 24-bit-per-pel modes as if they are 8-bit-per-pel modes with extremely wide scanlines. Because the drawing engine is addressing bytes rather than 24-bit pels, it is necessary to triple all coordinates before writing them to the hardware. Note that throughout the driver you will find the following construction for tripling coordinates:
fast3x: ;The fast way to triple ax mov bx, ax shl ax, 1 add ax, bx
The following is a faster way to triple ax on a 486 microprocessor.
; Triple eax fast3x: lea eax, [eax+2*eax]
In terms of changing the byte ordering of 24-bit-per-pel modes, the S3 driver supports two pel orderings, RGB and BGR. To change between the two, set or clear the bit USE_ATTDAC in DDT.fScreenFlags. The bit-map conversion code looks at this flag and performs the correct function, dependent upon its setting.
In terms of changing the byte ordering of 24-bit-per-pel modes, the S3 driver supports two pel orderings, RGB and BGR. The RGB pel ordering is supported by many RAM DACs and is the 'normal' ordering of pixels in 24-bit modes. In RGB pel ordering, the blue pel is first in memory, followed by the green pel, followed by the red pel. The RGB2 structure is defined with the same pel ordering:
typedef struct _RGB2 { /* rgb2 */ BYTE bBlue; /* Blue component of the color definition */ BYTE bGreen; /* Green component of the color definition */ BYTE bRed; /* Red component of the color definition */ BYTE fcOptions; /* Reserved, must be zero */ } RGB2; typedef RGB2 Far *PRGB2;
GB pel ordering is chosen by setting the USE_ATTDAC bit in the DDT.fScreenFlags. (Although the name of this bit implies that an AT&T** DAC is present, this is not so.) Clearing the USE_ATTDAC bit in the DTT.fScreenFlags forces BGR byte ordering which stores the red pel first, followed by the green pel, followed by the blue pel. The USE_ATTDAC bit forces all bit maps to use RGB byte ordering. Following is an example from CONVEXT.C:
/*********************************************************************/ /* ConvertEx24ToInt24 */ /* */ /* Converts a single scan ine from external 24bpp to internal 24bpp. */ /* (No convert table is used a 24 bpp. */ /*********************************************************************/ VOID ConvertExt24ToInt24 (VOID) { ULONG j; rgb TrgPel; for ( j = SPad.cx; j--;) { TrgPel = *((PRGB)SPad.pbSrcPointer); if ( !(DDT.fScreenFlags & USE_ATTDAC) ) { *((PBYTE)SPad.pbTrgPointer)++ = TrgPel.bBlue; *((PBYTE)SPad.pbTrgPointer)++ = TrgPel.bGreen; *((PBYTE)SPad.pbTrgPointer)++ = TrgPel.bRed; } else { *((PBYTE)SPad.pbTrgPointer)++ = TrgPel.bRed; *((PBYTE)SPad.pbTrgPointer)++ = TrgPel.bGreen; *((PBYTE)SPad.pbTrgPointer)++ = TrgPel.bBlue; } SPad.pbSrcPointer += sizeof(RGB); { } /* ConvertExt24ToInt24 */
When the USE_ATTDAC bit is set, the blue pel is first in memory and when USE_ATTDAC bit is not set, the red pel is first in memory. This is the code that translates an external bit map to an internal bit map. However 24-bit color values are not translated in the same way. This is shown in LogToPhyIndex in EDDCSUBR.C:
#ifdef BPP24 else if (DDT.BitCount == 24) { /*************************************************************/ /* Map the RGB2 value into an RGB24 value. (24bpp pel value) */ /*************************************************************/ if ( !(DDT.fScreenFlags & USE_ATTDAC) ) { PhyIndex = RGB24FromPRGB2(&RegRGB); } else { PhyIndex = RGBRGB24FromPRGB2(&RegRGB); } } #endif
The following RGB24From macros are located in CONVFUNS.H:
#define RGB24FromPRGB2(prgb2) XGA_RGB24FromPRGB2(prgb2) #define RGB24FromPRGB2ATT(prgb2) XGA_RGB24FromPRGB2ATT(prgb2) #define XGA_RGB24FromPRGB2(prgb2) *(PULONG)(prgb2) #define XGA_RGB24FromPRGB2ATT(prgb2) ((((ULONG)((prgb2)->bRed))) | \ (((ULONG)((prgb2)->bGreen)) <<8) | \ (((ULONG)((prgb2)->bBlue)) <<16) ) \
LogToPhyIndex is the routine responsible for translating the logical RGB2 values passed in from PM to colors that are realizable in the driver. It translates almost every color value used in the driver. When the USE_ATTDAC bit is not set, the color passed in is copied over directly, even though PM passes in RGB format colors. When the USE_ATTDAC bit is set, the color value is byte-swapped to BGR order. The following code in Copy24MonoToVRAM (HWACCESS.ASM) explains why this occurs:
;set the colors to expand to and put them in the correct format ;to write dwords mov edx,Shadow8514Regs.Color_1 mov ebx,Shadow8514Regs.Color_0 ror dx,8 ror edx,16 ror dx,8 ror edx,8 ror bx,8 ror ebx,8 ror dx,8 ror ebx,8
Copy24MonoToVRAM performs monochrome to color expansion in 24-bit-per-pel modes in the S3 driver. Notice that it is performing a byte-swap on the colors that were passed into it as arguments in the Shadow8514Regs. The reason the for this reversed color storage has to do with the implementation of eddf_MESS. In eddf_MESS, 24-bit colors are written in reverse order. Consequently, if your device supports 24-bit-per-pel operations in hardware, you must reverse the bytes of Shadow8514Regs.Color_0 and Color1 prior to writing them to the color registers of your hardware.