DOS_Video/accelVid.h
2026-04-13 19:40:45 -05:00

257 lines
11 KiB
C

// 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 <stdint.h>
#include <stdbool.h>
#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