// accelVid.h -- Accelerated video driver abstraction for DOS // // Defines the common interface that all hardware-specific video // drivers implement. Each driver fills in an AccelDriverT struct // with function pointers for its accelerated operations and sets // capability flags indicating which operations are hardware-backed. // // The driver manager (accelVid.c) iterates registered drivers, // calls detect() on each, and returns the first match. The caller // then uses the function pointers directly -- no dispatch overhead // beyond the initial detection. // // Operations that aren't hardware-accelerated on a given chip // should be left as NULL. The caller is responsible for falling // back to software rendering for NULL operations. Capability // flags in AccelDriverT.caps indicate which operations are // available so callers can check without testing each pointer. // // All coordinates and dimensions are in pixels. Colors are packed // in the display's native pixel format (same as DVX's packColor). #ifndef ACCEL_VID_H #define ACCEL_VID_H #include #include #include "pci.h" // ============================================================ // Capability flags // ============================================================ // // Bit flags indicating which operations are hardware-accelerated. // A driver sets these in its caps field during detect/init. The // caller can test (drv->caps & ACAP_xxx) to decide whether to // use hardware or fall back to software. #define ACAP_RECT_FILL 0x00000001 // solid rectangle fill #define ACAP_RECT_FILL_PAT 0x00000002 // pattern rectangle fill (8x8) #define ACAP_BITBLT 0x00000004 // screen-to-screen blit #define ACAP_COLOR_EXPAND 0x00000008 // mono-to-color expansion (text/glyphs) #define ACAP_LINE_DRAW 0x00000010 // Bresenham line drawing #define ACAP_HW_CURSOR 0x00000020 // hardware sprite cursor #define ACAP_HOST_BLIT 0x00000040 // CPU-to-screen blit (image upload) #define ACAP_CLIP 0x00000080 // hardware clip rectangle #define ACAP_TRANSPARENCY 0x00000100 // transparent blit (color key) // ============================================================ // Raster operation codes // ============================================================ // // Standard Microsoft/GDI ROP codes used by Windows drivers. // These map to the 256 possible ternary raster operations, but // we only define the commonly used ones. The hardware engines // typically support these natively. #define ROP_COPY 0xCC // dest = src #define ROP_PAT_COPY 0xF0 // dest = pattern #define ROP_ZERO 0x00 // dest = 0 (black) #define ROP_ONE 0xFF // dest = 1 (white) #define ROP_SRC_AND 0x88 // dest = src AND dest #define ROP_SRC_OR 0xEE // dest = src OR dest #define ROP_SRC_XOR 0x66 // dest = src XOR dest #define ROP_NOT 0x55 // dest = NOT dest #define ROP_PAT_AND 0xA0 // dest = pat AND dest #define ROP_PAT_OR 0xFA // dest = pat OR dest #define ROP_PAT_XOR 0x5A // dest = pat XOR dest // ============================================================ // Hardware cursor image format // ============================================================ // // Hardware cursors use a 2-bit-per-pixel AND/XOR format: // AND=0, XOR=0 -> cursor color 0 (background) // AND=0, XOR=1 -> cursor color 1 (foreground) // AND=1, XOR=0 -> transparent (screen shows through) // AND=1, XOR=1 -> inverted (screen pixel is inverted) // // Most chips support 64x64 cursors (S3, Matrox, ATI, Tseng W32p). // Older Cirrus (GD5426/28) support only 32x32. #define HW_CURSOR_MAX_SIZE 64 typedef struct { int32_t width; int32_t height; int32_t hotX; int32_t hotY; uint8_t andMask[HW_CURSOR_MAX_SIZE * HW_CURSOR_MAX_SIZE / 8]; uint8_t xorMask[HW_CURSOR_MAX_SIZE * HW_CURSOR_MAX_SIZE / 8]; } HwCursorImageT; // ============================================================ // Video mode request / result // ============================================================ typedef struct { int32_t width; int32_t height; int32_t bpp; // requested bits per pixel (8, 15, 16, 32) } AccelModeRequestT; typedef struct { int32_t width; int32_t height; int32_t bpp; int32_t pitch; // bytes per scanline (may be > width * bytesPerPixel) uint8_t *framebuffer; // mapped linear framebuffer pointer uint32_t vramSize; // total video RAM in bytes uint32_t offscreenBase; // offset to start of offscreen VRAM (for allocations) } AccelModeResultT; // ============================================================ // Driver structure // ============================================================ // // Each chip driver provides a statically-allocated AccelDriverT // and registers it with accelRegisterDriver(). The driver manager // calls detect() on each registered driver during accelInit(). // // The init() function receives a mode request and returns detailed // mode info. It is responsible for: // - Programming the CRTC/sequencer for the requested mode // - Enabling the linear framebuffer // - Unlocking the acceleration engine // - Setting up MMIO mappings if needed // // All accelerated drawing functions must call waitIdle() internally // before returning if the operation is asynchronous. The explicit // waitIdle() in the API is for synchronization points where the // caller needs to read back from VRAM after a series of operations. typedef struct AccelDriverT { // Driver identification const char *name; // human-readable name (e.g. "S3 Trio64") const char *chipFamily; // family identifier (e.g. "s3", "cirrus") uint32_t caps; // ACAP_xxx capability flags // PCI device info (filled by detect) PciDeviceT pciDev; // Current mode info (filled by init) AccelModeResultT mode; // -------------------------------------------------------- // Lifecycle // -------------------------------------------------------- // Probe for this chip. Returns true if this driver's hardware // is present. Must not change any hardware state. bool (*detect)(struct AccelDriverT *drv); // Initialize the chip: set the requested video mode, enable // acceleration, map the framebuffer. Returns true on success. bool (*init)(struct AccelDriverT *drv, const AccelModeRequestT *req); // Shut down: restore text mode, disable acceleration, unmap // memory. Safe to call even if init() was never called. void (*shutdown)(struct AccelDriverT *drv); // -------------------------------------------------------- // Synchronization // -------------------------------------------------------- // Wait until the acceleration engine is idle. All pending // drawing commands must complete before this returns. void (*waitIdle)(struct AccelDriverT *drv); // -------------------------------------------------------- // Hardware clip rectangle // -------------------------------------------------------- // Set the hardware clip rectangle. All subsequent drawing // operations are clipped to this region. Pass full-screen // dimensions to disable clipping. void (*setClip)(struct AccelDriverT *drv, int32_t x, int32_t y, int32_t w, int32_t h); // -------------------------------------------------------- // Accelerated drawing operations // -------------------------------------------------------- // Solid rectangle fill. void (*rectFill)(struct AccelDriverT *drv, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color); // Pattern rectangle fill (8x8 pattern, one color + transparent // or two-color). Pattern data is 8 bytes, one bit per pixel, // MSB-first, top row first. void (*rectFillPat)(struct AccelDriverT *drv, int32_t x, int32_t y, int32_t w, int32_t h, const uint8_t *pattern, uint32_t fg, uint32_t bg); // Screen-to-screen blit. void (*bitBlt)(struct AccelDriverT *drv, int32_t srcX, int32_t srcY, int32_t dstX, int32_t dstY, int32_t w, int32_t h); // CPU-to-screen blit: transfer pixels from system RAM to VRAM. // srcBuf points to packed pixel data in display format. // srcPitch is the byte stride of the source buffer. void (*hostBlit)(struct AccelDriverT *drv, const uint8_t *srcBuf, int32_t srcPitch, int32_t dstX, int32_t dstY, int32_t w, int32_t h); // Monochrome color expansion: convert 1bpp bitmap data to // full-color pixels. Used for fast text/glyph rendering. // srcBuf is packed MSB-first, one bit per pixel. // srcPitch is the byte stride between rows. void (*colorExpand)(struct AccelDriverT *drv, const uint8_t *srcBuf, int32_t srcPitch, int32_t dstX, int32_t dstY, int32_t w, int32_t h, uint32_t fg, uint32_t bg); // Bresenham line draw (inclusive endpoints). void (*lineDraw)(struct AccelDriverT *drv, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color); // -------------------------------------------------------- // Hardware cursor // -------------------------------------------------------- // Set the cursor image. Called when the cursor shape changes. void (*setCursor)(struct AccelDriverT *drv, const HwCursorImageT *image); // Move the cursor to a screen position. Called every mouse poll. void (*moveCursor)(struct AccelDriverT *drv, int32_t x, int32_t y); // Show or hide the hardware cursor. void (*showCursor)(struct AccelDriverT *drv, bool visible); // -------------------------------------------------------- // Private driver data // -------------------------------------------------------- // Opaque pointer for chip-specific state (MMIO base address, // current engine state, etc.). Each driver allocates and manages // its own private data. void *privData; } AccelDriverT; // ============================================================ // Driver manager API // ============================================================ // Register a driver with the manager. Call once per driver at // startup (typically from main before accelInit). Drivers are // probed in registration order. void accelRegisterDriver(AccelDriverT *drv); // Probe all registered drivers and return the first one whose // detect() succeeds. Returns NULL if no supported hardware is found. AccelDriverT *accelDetect(void); // Initialize the detected driver with the given mode. // Returns true on success. On failure the driver is not usable. bool accelInit(AccelDriverT *drv, const AccelModeRequestT *req); // Shut down the active driver and restore text mode. void accelShutdown(AccelDriverT *drv); // Return the driver name string for display. const char *accelGetName(const AccelDriverT *drv); // Return the capability flags for the active driver. uint32_t accelGetCaps(const AccelDriverT *drv); #endif // ACCEL_VID_H