257 lines
11 KiB
C
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
|