934 lines
42 KiB
C
934 lines
42 KiB
C
/******************************Module*Header*******************************\
|
|
*
|
|
* *******************
|
|
* * GDI SAMPLE CODE *
|
|
* *******************
|
|
*
|
|
* Module Name: driver.h
|
|
*
|
|
* Contains prototypes for the display driver.
|
|
*
|
|
* Copyright (c) 1992-1998 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Put all the conditional-compile constants here. There had better
|
|
// not be many!
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Miscellaneous shared stuff
|
|
|
|
#define DLL_NAME L"s3" // Name of the DLL in UNICODE
|
|
#define STANDARD_DEBUG_PREFIX "S3: " // All debug output is prefixed
|
|
// by this string
|
|
#define ALLOC_TAG ' 3S' // Four byte tag used for tracking
|
|
// memory allocations (characters
|
|
// are in reverse order)
|
|
|
|
#define CLIP_LIMIT 50 // We'll be taking 800 bytes of stack space
|
|
|
|
#define DRIVER_EXTRA_SIZE 0 // Size of the DriverExtra information in the
|
|
// DEVMODE structure
|
|
|
|
#define TMP_BUFFER_SIZE 8192 // Size in bytes of 'pvTmpBuffer'. Has to
|
|
// be at least enough to store an entire
|
|
// scan line (i.e., 6400 for 1600x1200x32).
|
|
|
|
#if defined(_ALPHA_)
|
|
#define XFER_BUFFERS 16 // Defines the maximum number of write buffers
|
|
// possible on any Alpha. Must be a power
|
|
#else // of two.
|
|
#define XFER_BUFFERS 1 // On non-alpha systems, we don't have to
|
|
// worry about the chip caching our bus
|
|
#endif // writes.
|
|
|
|
#define XFER_MASK (XFER_BUFFERS - 1)
|
|
|
|
typedef struct _CLIPENUM {
|
|
LONG c;
|
|
RECTL arcl[CLIP_LIMIT]; // Space for enumerating complex clipping
|
|
|
|
} CLIPENUM; /* ce, pce */
|
|
|
|
typedef struct _PDEV PDEV; // Handy forward declaration
|
|
|
|
VOID vSetClipping(PDEV*, RECTL*);
|
|
VOID vResetClipping(PDEV*);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Text stuff
|
|
|
|
#define GLYPH_CACHE_HEIGHT 48 // Number of scans to allocate for glyph cache,
|
|
// divided by pel size
|
|
|
|
#define GLYPH_CACHE_CX 64 // Maximal width of glyphs that we'll consider
|
|
// caching
|
|
|
|
#define GLYPH_CACHE_CY 64 // Maximum height of glyphs that we'll consider
|
|
// caching
|
|
|
|
#define MAX_GLYPH_SIZE ((GLYPH_CACHE_CX * GLYPH_CACHE_CY + 31) / 8)
|
|
// Maximum amount of off-screen memory required
|
|
// to cache a glyph, in bytes
|
|
|
|
#define GLYPH_ALLOC_SIZE 8100
|
|
// Do all cached glyph memory allocations
|
|
// in 8k chunks
|
|
|
|
#define HGLYPH_SENTINEL ((ULONG) -1)
|
|
// GDI will never give us a glyph with a
|
|
// handle value of 0xffffffff, so we can
|
|
// use this as a sentinel for the end of
|
|
// our linked lists
|
|
|
|
#define GLYPH_HASH_SIZE 256
|
|
|
|
#define GLYPH_HASH_FUNC(x) ((x) & (GLYPH_HASH_SIZE - 1))
|
|
|
|
typedef struct _CACHEDGLYPH CACHEDGLYPH;
|
|
typedef struct _CACHEDGLYPH
|
|
{
|
|
CACHEDGLYPH* pcgNext; // Points to next glyph that was assigned
|
|
// to the same hash table bucket
|
|
HGLYPH hg; // Handles in the bucket-list are kept in
|
|
// increasing order
|
|
POINTL ptlOrigin; // Origin of glyph bits
|
|
|
|
// Device specific fields below here:
|
|
|
|
LONG cxLessOne; // Glyph width less one
|
|
LONG cyLessOne; // Glyph height less one
|
|
LONG cxcyLessOne;// Packed width and height, less one
|
|
LONG cw; // Number of words to be transferred
|
|
LONG cd; // Number of dwords to be transferred
|
|
ULONG ad[1]; // Start of glyph bits
|
|
} CACHEDGLYPH; /* cg, pcg */
|
|
|
|
typedef struct _GLYPHALLOC GLYPHALLOC;
|
|
typedef struct _GLYPHALLOC
|
|
{
|
|
GLYPHALLOC* pgaNext; // Points to next glyph structure that
|
|
// was allocated for this font
|
|
CACHEDGLYPH acg[1]; // This array is a bit misleading, because
|
|
// the CACHEDGLYPH structures are actually
|
|
// variable sized
|
|
} GLYPHAALLOC; /* ga, pga */
|
|
|
|
typedef struct _CACHEDFONT CACHEDFONT;
|
|
typedef struct _CACHEDFONT
|
|
{
|
|
CACHEDFONT* pcfNext; // Points to next entry in CACHEDFONT list
|
|
CACHEDFONT* pcfPrev; // Points to previous entry in CACHEDFONT list
|
|
GLYPHALLOC* pgaChain; // Points to start of allocated memory list
|
|
CACHEDGLYPH* pcgNew; // Points to where in the current glyph
|
|
// allocation structure a new glyph should
|
|
// be placed
|
|
LONG cjAlloc; // Bytes remaining in current glyph allocation
|
|
// structure
|
|
CACHEDGLYPH cgSentinel; // Sentinel entry of the end of our bucket
|
|
// lists, with a handle of HGLYPH_SENTINEL
|
|
CACHEDGLYPH* apcg[GLYPH_HASH_SIZE];
|
|
// Hash table for glyphs
|
|
|
|
} CACHEDFONT; /* cf, pcf */
|
|
|
|
typedef struct _XLATECOLORS { // Specifies foreground and background
|
|
ULONG iBackColor; // colours for faking a 1bpp XLATEOBJ
|
|
ULONG iForeColor;
|
|
} XLATECOLORS; /* xlc, pxlc */
|
|
|
|
BOOL bEnableText(PDEV*);
|
|
VOID vDisableText(PDEV*);
|
|
VOID vAssertModeText(PDEV*, BOOL);
|
|
|
|
VOID vFastText(GLYPHPOS*, ULONG, BYTE*, ULONG, ULONG, RECTL*, RECTL*,
|
|
FLONG, RECTL*, RECTL*);
|
|
VOID vClearMemDword(ULONG*, ULONG);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Brush stuff
|
|
|
|
// 'Slow' brushes are used when we don't have hardware pattern capability,
|
|
// and we have to handle patterns using screen-to-screen blts:
|
|
|
|
#define SLOW_BRUSH_CACHE_DIM 3 // Controls the number of brushes cached
|
|
// in off-screen memory, when we don't
|
|
// have the S3 hardware pattern support.
|
|
// We allocate 3 x 3 brushes, so we can
|
|
// cache a total of 9 brushes:
|
|
#define SLOW_BRUSH_COUNT (SLOW_BRUSH_CACHE_DIM * SLOW_BRUSH_CACHE_DIM)
|
|
#define SLOW_BRUSH_DIMENSION 64 // After alignment is taken care of,
|
|
// every off-screen brush cache entry
|
|
// will be 64 pels in both dimensions
|
|
#define SLOW_BRUSH_ALLOCATION (SLOW_BRUSH_DIMENSION + 8)
|
|
// Actually allocate 72x72 pels for each
|
|
// pattern, using the 8 extra for brush
|
|
// alignment
|
|
|
|
// 'Fast' brushes are used when we have hardware pattern capability:
|
|
|
|
#define FAST_BRUSH_COUNT 16 // Total number of non-hardware brushes
|
|
// cached off-screen
|
|
#define FAST_BRUSH_DIMENSION 8 // Every off-screen brush cache entry
|
|
// is 8 pels in both dimensions
|
|
#define FAST_BRUSH_ALLOCATION 16 // We have to align ourselves, so this is
|
|
// the dimension of each brush allocation
|
|
|
|
// Common to both implementations:
|
|
|
|
#define RBRUSH_2COLOR 1 // For RBRUSH flags
|
|
|
|
#define TOTAL_BRUSH_COUNT max(FAST_BRUSH_COUNT, SLOW_BRUSH_COUNT)
|
|
// This is the maximum number of brushes
|
|
// we can possibly have cached off-screen
|
|
#define TOTAL_BRUSH_SIZE 64 // We'll only ever handle 8x8 patterns,
|
|
// and this is the number of pels
|
|
|
|
typedef struct _BRUSHENTRY BRUSHENTRY;
|
|
|
|
// NOTE: Changes to the RBRUSH or BRUSHENTRY structures must be reflected
|
|
// in strucs.inc!
|
|
|
|
typedef struct _RBRUSH {
|
|
FLONG fl; // Type flags
|
|
BOOL bTransparent; // TRUE if brush was realized for a transparent
|
|
// blt (meaning colours are white and black),
|
|
// FALSE if not (meaning it's already been
|
|
// colour-expanded to the correct colours).
|
|
// Value is undefined if the brush isn't
|
|
// 2 colour.
|
|
ULONG ulForeColor; // Foreground colour if 1bpp
|
|
ULONG ulBackColor; // Background colour if 1bpp
|
|
POINTL ptlBrushOrg; // Brush origin of cached pattern. Initial
|
|
// value should be -1
|
|
BRUSHENTRY* pbe; // Points to brush-entry that keeps track
|
|
// of the cached off-screen brush bits
|
|
ULONG aulPattern[1]; // Open-ended array for keeping copy of the
|
|
// Don't put anything // actual pattern bits in case the brush
|
|
// after here, or // origin changes, or someone else steals
|
|
// you'll be sorry! // our brush entry (declared as a ULONG
|
|
// for proper dword alignment)
|
|
|
|
} RBRUSH; /* rb, prb */
|
|
|
|
typedef struct _BRUSHENTRY {
|
|
RBRUSH* prbVerify; // We never dereference this pointer to
|
|
// find a brush realization; it is only
|
|
// ever used in a compare to verify
|
|
// that for a given realized brush, our
|
|
// off-screen brush entry is still valid.
|
|
LONG x; // x-position of cached pattern
|
|
LONG y; // y-position of cached pattern
|
|
|
|
} BRUSHENTRY; /* be, pbe */
|
|
|
|
typedef union _RBRUSH_COLOR {
|
|
RBRUSH* prb;
|
|
ULONG iSolidColor;
|
|
} RBRUSH_COLOR; /* rbc, prbc */
|
|
|
|
BOOL bEnableBrushCache(PDEV*);
|
|
VOID vDisableBrushCache(PDEV*);
|
|
VOID vAssertModeBrushCache(PDEV*, BOOL);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Stretch stuff
|
|
|
|
typedef struct _STR_BLT {
|
|
PDEV* ppdev;
|
|
PBYTE pjSrcScan;
|
|
LONG lDeltaSrc;
|
|
LONG XSrcStart;
|
|
PBYTE pjDstScan;
|
|
LONG lDeltaDst;
|
|
LONG XDstStart;
|
|
LONG XDstEnd;
|
|
LONG YDstStart;
|
|
LONG YDstCount;
|
|
ULONG ulXDstToSrcIntCeil;
|
|
ULONG ulXDstToSrcFracCeil;
|
|
ULONG ulYDstToSrcIntCeil;
|
|
ULONG ulYDstToSrcFracCeil;
|
|
ULONG ulXFracAccumulator;
|
|
ULONG ulYFracAccumulator;
|
|
} STR_BLT;
|
|
|
|
typedef VOID (*PFN_DIRSTRETCH)(STR_BLT*);
|
|
|
|
VOID vDirectStretch8Narrow(STR_BLT*);
|
|
VOID vDirectStretch8(STR_BLT*);
|
|
VOID vDirectStretch16(STR_BLT*);
|
|
VOID vDirectStretch32(STR_BLT*);
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// Heap stuff
|
|
|
|
typedef struct _DSURF DSURF;
|
|
|
|
typedef enum {
|
|
DT_DIB = 0x1, // Surface is really a DIB, not in off-screen
|
|
// memory
|
|
DT_DIRECTDRAW = 0x2, // Surface is really a DirectDraw surface
|
|
|
|
} DSURFTYPE; /* dt, pdt */
|
|
|
|
typedef struct _DSURF
|
|
{
|
|
DSURFTYPE dt; // DSURF status flags
|
|
PDEV* ppdev; // Points to our PDEV
|
|
LONG x; // x pixel coordinate of left edge of allocation
|
|
// if not DT_DIB
|
|
LONG y; // y pixel coordinate of right edge of allocation
|
|
// if not DT_DIB
|
|
LONG cx; // Bitmap width in pixels
|
|
LONG cy; // Bitmap height in pixels
|
|
union {
|
|
FLATPTR fpVidMem; // Offset from start of video-memory if not DT_DIB
|
|
VOID* pvScan0; // Bits location in system-memory if DT_DIB
|
|
};
|
|
VIDEOMEMORY* pvmHeap; // DirectDraw heap this was allocated from if
|
|
// not DT_DIB and not DT_DIRECTDRAW
|
|
DSURF* pdsurfDiscardableNext;
|
|
// Linked list of discardable surface allocations.
|
|
// This list is traversed from the start to
|
|
// throw out any allocations
|
|
HSURF hsurf; // Handle to associated GDI surface (if any)
|
|
|
|
// The following are used for DT_DIB only...
|
|
|
|
ULONG cBlt; // Counts down the number of blts necessary at
|
|
// the current uniqueness before we'll consider
|
|
// putting the DIB back into off-screen memory
|
|
ULONG iUniq; // Tells us whether there have been any heap
|
|
// 'free's since the last time we looked at
|
|
// this DIB
|
|
|
|
} DSURF; /* dsurf, pdsurf */
|
|
|
|
// Number of blts necessary before we'll consider putting a DIB DFB back
|
|
// into off-screen memory:
|
|
|
|
#define HEAP_COUNT_DOWN 6
|
|
|
|
DSURF* pVidMemAllocate(PDEV*, LONG, LONG);
|
|
VOID vVidMemFree(DSURF*);
|
|
BOOL bMoveDibToOffscreenDfbIfRoom(PDEV*, DSURF*);
|
|
BOOL bMoveOldestOffscreenDfbToDib(PDEV*);
|
|
|
|
BOOL bEnableOffscreenHeap(PDEV*);
|
|
VOID vDisableOffscreenHeap(PDEV*);
|
|
BOOL bAssertModeOffscreenHeap(PDEV*, BOOL);
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// Bank manager stuff
|
|
|
|
#define BANK_DATA_SIZE 80 // Number of bytes to allocate for the
|
|
// miniport down-loaded bank code working
|
|
// space
|
|
|
|
typedef struct _BANK
|
|
{
|
|
// Private data:
|
|
|
|
RECTL rclDraw; // Rectangle describing the remaining undrawn
|
|
// portion of the drawing operation
|
|
RECTL rclSaveBounds; // Saved from original CLIPOBJ for restoration
|
|
BYTE iSaveDComplexity; // Saved from original CLIPOBJ for restoration
|
|
BYTE fjSaveOptions; // Saved from original CLIPOBJ for restoration
|
|
LONG iBank; // Current bank
|
|
PDEV* ppdev; // Saved copy
|
|
|
|
// Public data:
|
|
|
|
SURFOBJ* pso; // Surface wrapped around the bank. Has to be
|
|
// passed as the surface in any banked call-
|
|
// back.
|
|
CLIPOBJ* pco; // Clip object that is the intersection of the
|
|
// original clip object with the bounds of the
|
|
// current bank. Has to be passed as the clip
|
|
// object in any banked call-back.
|
|
|
|
} BANK; /* bnk, pbnk */
|
|
|
|
// Note: BANK_MODE is duplicated in i386\strucs.inc!
|
|
|
|
typedef enum {
|
|
BANK_OFF = 0, // We've finished using the memory aperture
|
|
BANK_ON, // We're about to use the memory aperture
|
|
BANK_ON_NO_WAIT, // We're about to use the memory aperture, and are
|
|
// doing our own hardware synchronization
|
|
BANK_DISABLE, // We're about to enter full-screen; shut down banking
|
|
BANK_ENABLE, // We've exited full-screen; re-enable banking
|
|
|
|
} BANK_MODE; /* bankm, pbankm */
|
|
|
|
typedef struct _BANKDATA {
|
|
|
|
// Common to both old and new bank schemes:
|
|
|
|
ULONG ulGp_stat_cmd; // Port number of status register
|
|
ULONG ulRegisterLock_35; // Default for index 35
|
|
|
|
// Only applies to new bank schemes:
|
|
|
|
ULONG ulSystemConfiguration_40; // Default for index 40
|
|
ULONG ulExtendedSystemControl2_51; // Default for index 51
|
|
ULONG ulExtendedMemoryControl_53; // Default for index 53
|
|
ULONG ulLinearAddressWindowControl_58; // Default for index 58
|
|
ULONG ulExtendedSystemControl4_6a; // Default for index 6a
|
|
|
|
ULONG ulEnableMemoryMappedIo; // Bit mask to enable MM IO
|
|
|
|
} BANKDATA; /* bd, pbd */
|
|
|
|
typedef VOID (FNBANKMAP)(PDEV*, BANKDATA*, LONG);
|
|
typedef VOID (FNBANKSELECTMODE)(PDEV*, BANKDATA*, BANK_MODE);
|
|
typedef VOID (FNBANKINITIALIZE)(PDEV*, BANKDATA*, BOOL);
|
|
typedef BOOL (FNBANKCOMPUTE)(PDEV*, RECTL*, RECTL*, LONG*, LONG*);
|
|
|
|
VOID vBankStart(PDEV*, RECTL*, CLIPOBJ*, BANK*);
|
|
BOOL bBankEnum(BANK*);
|
|
|
|
FNBANKCOMPUTE bBankComputeNonPower2;
|
|
FNBANKCOMPUTE bBankComputePower2;
|
|
|
|
BOOL bEnableBanking(PDEV*);
|
|
VOID vDisableBanking(PDEV*);
|
|
VOID vAssertModeBanking(PDEV*, BOOL);
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// Pointer stuff
|
|
|
|
#define POINTER_DATA_SIZE 40 // Number of bytes to allocate for the
|
|
// miniport down-loaded pointer code
|
|
// working space
|
|
#define HW_INVISIBLE_OFFSET 2 // Offset from 'ppdev->yPointerBuffer'
|
|
// to the invisible pointer
|
|
#define HW_POINTER_DIMENSION 64 // Maximum dimension of default
|
|
// (built-in) hardware pointer
|
|
#define HW_POINTER_HIDE 63 // Hardware pointer start pixel
|
|
// position used to hide the pointer
|
|
#define HW_POINTER_TOTAL_SIZE 1024 // Total size in bytes required
|
|
// to define the hardware pointer
|
|
// (must be a power of 2 for
|
|
// allocating space for the shape)
|
|
|
|
typedef VOID (FNSHOWPOINTER)(PDEV*, VOID*, BOOL);
|
|
typedef VOID (FNMOVEPOINTER)(PDEV*, VOID*, LONG, LONG);
|
|
typedef BOOL (FNSETPOINTERSHAPE)(PDEV*, VOID*, LONG, LONG, LONG, LONG, LONG,
|
|
LONG, BYTE*);
|
|
typedef VOID (FNENABLEPOINTER)(PDEV*, VOID*, BOOL);
|
|
|
|
BOOL bEnablePointer(PDEV*);
|
|
VOID vDisablePointer(PDEV*);
|
|
VOID vAssertModePointer(PDEV*, BOOL);
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// Palette stuff
|
|
|
|
BOOL bEnablePalette(PDEV*);
|
|
VOID vDisablePalette(PDEV*);
|
|
VOID vAssertModePalette(PDEV*, BOOL);
|
|
|
|
BOOL bInitializePalette(PDEV*, DEVINFO*);
|
|
VOID vUninitializePalette(PDEV*);
|
|
|
|
#define MAX_CLUT_SIZE (sizeof(VIDEO_CLUT) + (sizeof(ULONG) * 256))
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// DirectDraw stuff
|
|
|
|
DWORD DdBlt(PDD_BLTDATA);
|
|
DWORD DdFlip(PDD_FLIPDATA);
|
|
DWORD DdLock(PDD_LOCKDATA);
|
|
DWORD DdGetBltStatus(PDD_GETBLTSTATUSDATA);
|
|
DWORD DdMapMemory(PDD_MAPMEMORYDATA);
|
|
DWORD DdGetFlipStatus(PDD_GETFLIPSTATUSDATA);
|
|
DWORD DdWaitForVerticalBlank(PDD_WAITFORVERTICALBLANKDATA);
|
|
DWORD DdCanCreateSurface(PDD_CANCREATESURFACEDATA);
|
|
DWORD DdCreateSurface(PDD_CREATESURFACEDATA);
|
|
DWORD DdSetColorKey(PDD_SETCOLORKEYDATA);
|
|
DWORD DdUpdateOverlay(PDD_UPDATEOVERLAYDATA);
|
|
DWORD DdSetOverlayPosition(PDD_SETOVERLAYPOSITIONDATA);
|
|
DWORD DdGetDriverInfo(PDD_GETDRIVERINFODATA);
|
|
|
|
// FourCC formats are encoded in reverse because we're little endian:
|
|
|
|
#define FOURCC_YUY2 '2YUY' // Encoded in reverse because we're little
|
|
|
|
// There's a 64K granularity that applies to the mapping of the frame
|
|
// buffer into the application's address space:
|
|
|
|
#define ROUND_UP_TO_64K(x) (((ULONG)(x) + 0x10000 - 1) & ~(0x10000 - 1))
|
|
|
|
typedef struct _FLIPRECORD
|
|
{
|
|
FLATPTR fpFlipFrom; // Surface we last flipped from
|
|
LONGLONG liFlipTime; // Time at which last flip
|
|
// occured
|
|
LONGLONG liFlipDuration; // Precise amount of time it
|
|
// takes from vblank to vblank
|
|
BOOL bHaveEverCrossedVBlank; // True if we noticed that we
|
|
// switched from inactive to
|
|
// vblank
|
|
BOOL bWasEverInDisplay; // True if we ever noticed that
|
|
// we were inactive
|
|
BOOL bFlipFlag; // True if we think a flip is
|
|
// still pending
|
|
} FLIPRECORD;
|
|
|
|
BOOL bEnableDirectDraw(PDEV*);
|
|
VOID vDisableDirectDraw(PDEV*);
|
|
VOID vAssertModeDirectDraw(PDEV*, BOOL);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Low-level blt function prototypes
|
|
|
|
typedef VOID (FNFILL)(PDEV*, LONG, RECTL*, ULONG, RBRUSH_COLOR, POINTL*);
|
|
typedef VOID (FNXFER)(PDEV*, LONG, RECTL*, ULONG, SURFOBJ*, POINTL*,
|
|
RECTL*, XLATEOBJ*);
|
|
typedef VOID (FNCOPY)(PDEV*, LONG, RECTL*, ULONG, POINTL*, RECTL*);
|
|
typedef VOID (FNFASTPATREALIZE)(PDEV*, RBRUSH*, POINTL*, BOOL);
|
|
typedef VOID (FNIMAGETRANSFER)(PDEV*, BYTE*, LONG, LONG, LONG, ULONG);
|
|
typedef BOOL (FNTEXTOUT)(SURFOBJ*, STROBJ*, FONTOBJ*, CLIPOBJ*, RECTL*,
|
|
BRUSHOBJ*, BRUSHOBJ*);
|
|
typedef VOID (FNLINETOTRIVIAL)(PDEV*, LONG, LONG, LONG, LONG, ULONG, MIX);
|
|
typedef VOID (FNLINETOCLIPPED)(PDEV*, LONG, LONG, LONG, LONG, ULONG, MIX, RECTL*);
|
|
typedef VOID (FNCOPYTRANSPARENT)(PDEV*, LONG, RECTL*, POINTL*, RECTL*, ULONG);
|
|
|
|
FNFILL vIoFillPatFast;
|
|
FNFILL vIoFillPatSlow;
|
|
FNFILL vIoFillSolid;
|
|
FNXFER vIoXfer1bpp;
|
|
FNXFER vIoXfer4bpp;
|
|
FNXFER vIoXferNative;
|
|
FNXFER vXferNativeSrccopy;
|
|
FNCOPY vIoCopyBlt;
|
|
FNFASTPATREALIZE vIoFastPatRealize;
|
|
FNIMAGETRANSFER vIoImageTransferIo16;
|
|
FNIMAGETRANSFER vIoImageTransferMm16;
|
|
FNTEXTOUT bIoTextOut;
|
|
FNLINETOTRIVIAL vIoLineToTrivial;
|
|
FNLINETOCLIPPED vIoLineToClipped;
|
|
FNCOPYTRANSPARENT vIoCopyTransparent;
|
|
|
|
FNFILL vMmFillPatFast;
|
|
FNFILL vMmFillPatSlow;
|
|
FNFILL vMmFillSolid;
|
|
FNXFER vMmXfer1bpp;
|
|
FNXFER vMmXfer4bpp;
|
|
FNXFER vMmXferNative;
|
|
FNCOPY vMmCopyBlt;
|
|
FNFASTPATREALIZE vMmFastPatRealize;
|
|
FNIMAGETRANSFER vMmImageTransferMm16;
|
|
FNIMAGETRANSFER vMmImageTransferMm32;
|
|
FNTEXTOUT bMmTextOut;
|
|
FNLINETOTRIVIAL vMmLineToTrivial;
|
|
FNLINETOCLIPPED vMmLineToClipped;
|
|
FNCOPYTRANSPARENT vMmCopyTransparent;
|
|
|
|
FNTEXTOUT bNwTextOut;
|
|
FNLINETOTRIVIAL vNwLineToTrivial;
|
|
FNLINETOCLIPPED vNwLineToClipped;
|
|
|
|
VOID vPutBits(PDEV*, SURFOBJ*, RECTL*, POINTL*);
|
|
VOID vGetBits(PDEV*, SURFOBJ*, RECTL*, POINTL*);
|
|
VOID vIoSlowPatRealize(PDEV*, RBRUSH*, BOOL);
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// Capabilities flags
|
|
//
|
|
// These are private flags passed to us from the S3 miniport. They
|
|
// come from the 'DriverSpecificAttributeFlags' field of the
|
|
// 'VIDEO_MODE_INFORMATION' structure (found in 'ntddvdeo.h') passed
|
|
// to us via an 'VIDEO_QUERY_AVAIL_MODES' or 'VIDEO_QUERY_CURRENT_MODE'
|
|
// IOCTL.
|
|
//
|
|
// NOTE: These definitions must match those in the S3 miniport's 's3.h'!
|
|
|
|
typedef enum {
|
|
CAPS_STREAMS_CAPABLE = 0x00000040, // Has overlay streams processor
|
|
CAPS_FORCE_DWORD_REREADS= 0x00000080, // Dword reads occasionally return
|
|
// an incorrect result, so always
|
|
// retry the reads
|
|
CAPS_NEW_MMIO = 0x00000100, // Can use 'new memory-mapped
|
|
// I/O' scheme introduced with
|
|
// 868/968
|
|
CAPS_POLYGON = 0x00000200, // Can do polygons in hardware
|
|
CAPS_24BPP = 0x00000400, // Has 24bpp capability
|
|
CAPS_BAD_24BPP = 0x00000800, // Has 868/968 early rev chip bugs
|
|
// when at 24bpp
|
|
CAPS_PACKED_EXPANDS = 0x00001000, // Can do 'new 32-bit transfers'
|
|
CAPS_PIXEL_FORMATTER = 0x00002000, // Can do colour space conversions,
|
|
// and one-dimensional hardware
|
|
// stretches
|
|
CAPS_BAD_DWORD_READS = 0x00004000, // Dword or word reads from the
|
|
// frame buffer will occasionally
|
|
// return an incorrect result,
|
|
// so always do byte reads
|
|
CAPS_NO_DIRECT_ACCESS = 0x00008000, // Frame buffer can't be directly
|
|
// accessed by GDI or DCI --
|
|
// because dword or word reads
|
|
// would crash system, or Alpha
|
|
// is running in sparse space
|
|
|
|
CAPS_HW_PATTERNS = 0x00010000, // 8x8 hardware pattern support
|
|
CAPS_MM_TRANSFER = 0x00020000, // Memory-mapped image transfers
|
|
CAPS_MM_IO = 0x00040000, // Memory-mapped I/O
|
|
CAPS_MM_32BIT_TRANSFER = 0x00080000, // Can do 32bit bus size transfers
|
|
CAPS_16_ENTRY_FIFO = 0x00100000, // At least 16 entries in FIFO
|
|
CAPS_SW_POINTER = 0x00200000, // No hardware pointer; use software
|
|
// simulation
|
|
CAPS_BT485_POINTER = 0x00400000, // Use Brooktree 485 pointer
|
|
CAPS_TI025_POINTER = 0x00800000, // Use TI TVP3020/3025 pointer
|
|
CAPS_SCALE_POINTER = 0x01000000, // Set if the S3 hardware pointer
|
|
// x position has to be scaled by
|
|
// two
|
|
CAPS_SPARSE_SPACE = 0x02000000, // Frame buffer is mapped in sparse
|
|
// space on the Alpha
|
|
CAPS_NEW_BANK_CONTROL = 0x04000000, // Set if 801/805/928 style banking
|
|
CAPS_NEWER_BANK_CONTROL = 0x08000000, // Set if 864/964 style banking
|
|
CAPS_RE_REALIZE_PATTERN = 0x10000000, // Set if we have to work around the
|
|
// 864/964 hardware pattern bug
|
|
CAPS_SLOW_MONO_EXPANDS = 0x20000000, // Set if we have to slow down
|
|
// monochrome expansions
|
|
CAPS_MM_GLYPH_EXPAND = 0x40000000, // Use memory-mapped I/O glyph-
|
|
// expand method of drawing text
|
|
} CAPS;
|
|
|
|
#define CAPS_DAC_POINTER (CAPS_BT485_POINTER | CAPS_TI025_POINTER)
|
|
|
|
#define CAPS_LINEAR_FRAMEBUFFER CAPS_NEW_MMIO
|
|
// For now, we're linear only
|
|
// when using with 'New MM I/O'
|
|
|
|
// DIRECT_ACCESS(ppdev) returns TRUE if GDI and DCI can directly access
|
|
// the frame buffer. It returns FALSE if there are hardware bugs
|
|
// when reading words or dwords from the frame buffer that cause non-x86
|
|
// systems to crash. It will also return FALSE is the Alpha frame buffer
|
|
// is mapped in using 'sparse space'.
|
|
|
|
#if defined(_X86_)
|
|
#define DIRECT_ACCESS(ppdev) 1
|
|
#else
|
|
#define DIRECT_ACCESS(ppdev) \
|
|
(!(ppdev->flCaps & (CAPS_NO_DIRECT_ACCESS | CAPS_SPARSE_SPACE)))
|
|
#endif
|
|
|
|
// DENSE(ppdev) returns TRUE if the normal 'dense space' mapping of the
|
|
// frame buffer is being used. It returns FALSE only on the Alpha when
|
|
// the frame buffer is mapped in using 'sparse space,' meaning that all
|
|
// reads and writes to and from the frame buffer must be done through the
|
|
// funky 'ioaccess.h' macros.
|
|
|
|
#if defined(_ALPHA_)
|
|
#define DENSE(ppdev) (!(ppdev->flCaps & CAPS_SPARSE_SPACE))
|
|
#else
|
|
#define DENSE(ppdev) 1
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// Status flags
|
|
|
|
typedef enum {
|
|
STAT_GLYPH_CACHE = 0x0001, // Glyph cache successfully allocated
|
|
STAT_BRUSH_CACHE = 0x0002, // Brush cache successfully allocated
|
|
STAT_DIRECTDRAW_CAPABLE = 0x0004, // Card is DirectDraw capable
|
|
STAT_STREAMS_ENABLED = 0x0010, // Streams processor is enabled
|
|
} STATUS;
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// The Physical Device data structure
|
|
|
|
typedef struct _PDEV
|
|
{
|
|
// -------------------------------------------------------------------
|
|
// NOTE: Changes between here and NOTE1 in the PDEV structure must be
|
|
// reflected in i386\strucs.inc (assuming you're on an x86, of course)!
|
|
|
|
LONG xOffset; // Pixel offset from (0, 0) to current
|
|
LONG yOffset; // DFB located in off-screen memory
|
|
BYTE* pjMmBase; // Start of memory mapped I/O
|
|
BYTE* pjScreen; // Points to base screen address
|
|
LONG lDelta; // Distance from one scan to the next.
|
|
LONG cjPelSize; // 1 if 8bpp, 2 if 16bpp, 3 if 24bpp,
|
|
// 4 if 32bpp
|
|
ULONG iBitmapFormat; // BMF_8BPP or BMF_16BPP or BMF_32BPP
|
|
// (our current colour depth)
|
|
|
|
// Enhanced mode register addresses.
|
|
|
|
VOID* ioCur_y;
|
|
VOID* ioCur_x;
|
|
VOID* ioDesty_axstp;
|
|
VOID* ioDestx_diastp;
|
|
VOID* ioErr_term;
|
|
VOID* ioMaj_axis_pcnt;
|
|
VOID* ioGp_stat_cmd;
|
|
VOID* ioShort_stroke;
|
|
VOID* ioBkgd_color;
|
|
VOID* ioFrgd_color;
|
|
VOID* ioWrt_mask;
|
|
VOID* ioRd_mask;
|
|
VOID* ioColor_cmp;
|
|
VOID* ioBkgd_mix;
|
|
VOID* ioFrgd_mix;
|
|
VOID* ioMulti_function;
|
|
VOID* ioPix_trans;
|
|
|
|
// Important data for accessing the frame buffer.
|
|
|
|
VOID* pvBankData; // Points to aulBankData[0]
|
|
FNBANKSELECTMODE* pfnBankSelectMode; // Routine to enable or disable
|
|
// direct frame buffer access
|
|
BANK_MODE bankmOnOverlapped; // BANK_ON or BANK_ON_NO_WAIT,
|
|
// depending on whether card
|
|
// can handle simulataneous
|
|
// frame buffer and accelerator
|
|
// access
|
|
BOOL bMmIo; // Can do CAPS_MM_IO
|
|
|
|
// -------------------------------------------------------------------
|
|
// NOTE1: Changes up to here in the PDEV structure must be reflected in
|
|
// i386\strucs.inc (assuming you're on an x86, of course)!
|
|
|
|
CAPS flCaps; // Capabilities flags
|
|
STATUS flStatus; // Status flags
|
|
BOOL bEnabled; // In graphics mode (not full-screen)
|
|
|
|
HANDLE hDriver; // Handle to \Device\Screen
|
|
HDEV hdevEng; // Engine's handle to PDEV
|
|
HSURF hsurfScreen; // Engine's handle to screen surface
|
|
|
|
LONG cxScreen; // Visible screen width
|
|
LONG cyScreen; // Visible screen height
|
|
LONG cxMemory; // Width of Video RAM
|
|
LONG cyHeap; // Height of Video RAM available to
|
|
// DirectDraw heap (cyScreen
|
|
// <= cyHeap <= cyMemory),
|
|
// including primary surface
|
|
LONG cxHeap; // Width of Video RAM available to
|
|
// DirectDraw heap, including
|
|
// primary surface
|
|
LONG cyMemory; // Height of Video RAM
|
|
LONG cBitsPerPel; // Bits per pel (8, 15, 16, 24 or 32)
|
|
ULONG ulMode; // Mode the mini-port driver is in.
|
|
FLONG flHooks; // What we're hooking from GDI
|
|
UCHAR* pjIoBase; // Mapped IO port base for this PDEV
|
|
VOID* pvTmpBuffer; // General purpose temporary buffer,
|
|
// TMP_BUFFER_SIZE bytes in size
|
|
// (Remember to synchronize if you
|
|
// use this for device bitmaps or
|
|
// async pointers)
|
|
USHORT* apwMmXfer[XFER_BUFFERS];// Pre-computed array of unique
|
|
ULONG* apdMmXfer[XFER_BUFFERS];// addresses for doing memory-mapped
|
|
// transfers without memory barriers
|
|
// Note that the 868/968 chips have a
|
|
// hardware bug and can't do byte
|
|
// transfers
|
|
HSEMAPHORE csCrtc; // Used for synchronizing access to
|
|
// the CRTC register
|
|
DSURF dsurfScreen; // We stash here our private surface
|
|
// structure that represents the
|
|
// primary GDI surface
|
|
|
|
////////// Low-level blt function pointers:
|
|
|
|
FNFILL* pfnFillSolid;
|
|
FNFILL* pfnFillPat;
|
|
FNXFER* pfnXfer1bpp;
|
|
FNXFER* pfnXfer4bpp;
|
|
FNXFER* pfnXferNative;
|
|
FNCOPY* pfnCopyBlt;
|
|
FNFASTPATREALIZE* pfnFastPatRealize;
|
|
FNIMAGETRANSFER* pfnImageTransfer;
|
|
FNTEXTOUT* pfnTextOut;
|
|
FNLINETOTRIVIAL* pfnLineToTrivial;
|
|
FNLINETOCLIPPED* pfnLineToClipped;
|
|
FNCOPYTRANSPARENT* pfnCopyTransparent;
|
|
|
|
////////// Palette stuff:
|
|
|
|
PALETTEENTRY* pPal; // The palette if palette managed
|
|
HPALETTE hpalDefault; // GDI handle to the default palette.
|
|
FLONG flRed; // Red mask for 16/32bpp bitfields
|
|
FLONG flGreen; // Green mask for 16/32bpp bitfields
|
|
FLONG flBlue; // Blue mask for 16/32bpp bitfields
|
|
ULONG cPaletteShift; // number of bits the 8-8-8 palette must
|
|
// be shifted by to fit in the hardware
|
|
// palette.
|
|
////////// Heap stuff:
|
|
|
|
VIDEOMEMORY* pvmList; // Points to the video-memory heap list
|
|
// as supplied by DirectDraw, needed
|
|
// for heap allocations
|
|
ULONG cHeaps; // Count of video-memory heaps
|
|
ULONG iHeapUniq; // Incremented every time room is freed
|
|
// in the off-screen heap
|
|
SURFOBJ* psoPunt; // Wrapper surface for having GDI draw
|
|
// on off-screen bitmaps
|
|
SURFOBJ* psoPunt2; // Another one for off-screen to off-
|
|
// screen blts
|
|
DSURF* pdsurfDiscardableList; // Linked list of discardable bitmaps,
|
|
// in order of oldest to newest
|
|
|
|
////////// Banking stuff:
|
|
|
|
LONG cjBank; // Size of a bank, in bytes
|
|
LONG cPower2ScansPerBank; // Used by 'bBankComputePower2'
|
|
LONG cPower2BankSizeInBytes; // Used by 'bBankComputePower2'
|
|
CLIPOBJ* pcoBank; // Clip object for banked call backs
|
|
SURFOBJ* psoBank; // Surface object for banked call backs
|
|
ULONG aulBankData[BANK_DATA_SIZE / 4];
|
|
// Private work area for downloaded
|
|
// miniport banking code
|
|
|
|
FNBANKMAP* pfnBankMap;
|
|
FNBANKCOMPUTE* pfnBankCompute;
|
|
|
|
////////// Pointer stuff:
|
|
|
|
BOOL bHwPointerActive; // Currently using the h/w pointer?
|
|
LONG xPointerHot; // xHot of current hardware pointer
|
|
LONG yPointerHot; // yHot of current hardware pointer
|
|
|
|
LONG cjPointerOffset; // Byte offset from start of frame
|
|
// buffer to off-screen memory where
|
|
// we stored the pointer shape
|
|
LONG xPointerShape; // x-coordinate
|
|
LONG yPointerShape; // y-coordinate
|
|
LONG iPointerBank; // Bank containing pointer shape
|
|
VOID* pvPointerShape; // Points to pointer shape when bank
|
|
// is mapped in
|
|
LONG xPointer; // Start x-position for the current
|
|
// S3 pointer
|
|
LONG yPointer; // Start y-position for the current
|
|
// S3 pointer
|
|
LONG dxPointer; // Start x-pixel position for the
|
|
// current S3 pointer
|
|
LONG dyPointer; // Start y-pixel position for the
|
|
// current S3 pointer
|
|
LONG cPointerShift; // Horizontal scaling factor for
|
|
// hardware pointer position
|
|
|
|
ULONG ulHwGraphicsCursorModeRegister_45;
|
|
// Default value for index 45
|
|
VOID* pvPointerData; // Points to ajPointerData[0]
|
|
BYTE ajPointerData[POINTER_DATA_SIZE];
|
|
// Private work area for downloaded
|
|
// miniport pointer code
|
|
|
|
FNSHOWPOINTER* pfnShowPointer;
|
|
FNMOVEPOINTER* pfnMovePointer;
|
|
FNSETPOINTERSHAPE* pfnSetPointerShape;
|
|
FNENABLEPOINTER* pfnEnablePointer;
|
|
|
|
////////// Brush stuff:
|
|
|
|
LONG iBrushCache; // Index for next brush to be allocated
|
|
LONG cBrushCache; // Total number of brushes cached
|
|
BRUSHENTRY abe[TOTAL_BRUSH_COUNT]; // Keeps track of brush cache
|
|
POINTL ptlReRealize; // Work area for 864/964 pattern
|
|
// hardware bug work-around
|
|
|
|
////////// Text stuff:
|
|
|
|
SURFOBJ* psoText; // 1bpp surface to which we will have
|
|
// GDI draw our glyphs for us
|
|
|
|
/////////// DirectDraw stuff:
|
|
|
|
FLIPRECORD flipRecord; // Used to track vertical blank status
|
|
ULONG ulRefreshRate; // Refresh rate in Hz
|
|
ULONG ulMinOverlayStretch; // Minimum stretch ratio for this mode,
|
|
// expressed as a multiple of 1000
|
|
ULONG ulFifoValue; // Optimial FIFO value for this mode
|
|
ULONG ulExtendedSystemControl3Register_69;
|
|
// Masked original contents of
|
|
// S3 register 0x69, in high byte
|
|
ULONG ulMiscState; // Default state of the MULT_MISC
|
|
// register
|
|
DSURF* pdsurfVideoEngineScratch;// Location of one entire scan line that
|
|
// can be used for temporary memory
|
|
// by the 868/968 pixel formatter
|
|
BYTE jSavedCR2; // Saved contents of register CR2
|
|
FLATPTR fpVisibleOverlay; // Frame buffer offset to currently
|
|
// visible overlay; will be zero if
|
|
// no overlay is visible
|
|
DWORD dwOverlayFlipOffset; // Overlay flip offset
|
|
DWORD dwVEstep; // 868 video engine step value
|
|
DWORD ulColorKey; // color key value to be set when streams
|
|
// processor is enabled
|
|
} PDEV;
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// Miscellaneous prototypes:
|
|
|
|
BOOL bIntersect(RECTL*, RECTL*, RECTL*);
|
|
LONG cIntersect(RECTL*, RECTL*, LONG);
|
|
DWORD getAvailableModes(HANDLE, PVIDEO_MODE_INFORMATION*, DWORD*);
|
|
|
|
BOOL bInitializeModeFields(PDEV*, GDIINFO*, DEVINFO*, DEVMODEW*);
|
|
BOOL bFastFill(PDEV*, LONG, POINTFIX*, ULONG, ULONG, RBRUSH*, POINTL*, RECTL*);
|
|
|
|
BOOL bEnableHardware(PDEV*);
|
|
VOID vDisableHardware(PDEV*);
|
|
BOOL bAssertModeHardware(PDEV*, BOOL);
|
|
|
|
extern BYTE gajHwMixFromMix[];
|
|
extern BYTE gaRop3FromMix[];
|
|
extern ULONG gaulHwMixFromRop2[];
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// The x86 C compiler insists on making a divide and modulus operation
|
|
// into two DIVs, when it can in fact be done in one. So we use this
|
|
// macro.
|
|
//
|
|
// Note: QUOTIENT_REMAINDER implicitly takes unsigned arguments.
|
|
|
|
#if defined(_X86_)
|
|
|
|
#define QUOTIENT_REMAINDER(ulNumerator, ulDenominator, ulQuotient, ulRemainder) \
|
|
{ \
|
|
__asm mov eax, ulNumerator \
|
|
__asm sub edx, edx \
|
|
__asm div ulDenominator \
|
|
__asm mov ulQuotient, eax \
|
|
__asm mov ulRemainder, edx \
|
|
}
|
|
|
|
#else
|
|
|
|
#define QUOTIENT_REMAINDER(ulNumerator, ulDenominator, ulQuotient, ulRemainder) \
|
|
{ \
|
|
ulQuotient = (ULONG) ulNumerator / (ULONG) ulDenominator; \
|
|
ulRemainder = (ULONG) ulNumerator % (ULONG) ulDenominator; \
|
|
}
|
|
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// OVERLAP - Returns TRUE if the same-size lower-right exclusive
|
|
// rectangles defined by 'pptl' and 'prcl' overlap:
|
|
|
|
#define OVERLAP(prcl, pptl) \
|
|
(((prcl)->right > (pptl)->x) && \
|
|
((prcl)->bottom > (pptl)->y) && \
|
|
((prcl)->left < ((pptl)->x + (prcl)->right - (prcl)->left)) && \
|
|
((prcl)->top < ((pptl)->y + (prcl)->bottom - (prcl)->top)))
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// SWAP - Swaps the value of two variables, using a temporary variable
|
|
|
|
#define SWAP(a, b, tmp) { (tmp) = (a); (a) = (b); (b) = (tmp); }
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// CONVERT_TO_BYTES - Converts to byte count.
|
|
|
|
#define CONVERT_TO_BYTES(x, pdev) ( (x) * pdev->cjPelSize)
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// CONVERT_FROM_BYTES - Converts to byte count.
|
|
|
|
#define CONVERT_FROM_BYTES(x, pdev) ( (x) / pdev->cjPelSize)
|