"fairie magic" written by Anders F Björklund <afb@algonet.se>
Routines | Platforms | Using BlitPixie | Prototypes |
Routines | Platforms | Using BlitPixie | Prototypes |
The blitters come in one or several of four versions:
Supported compilers:
The assembly versions use CodeWarrior's inline assembly, with some #defines to make stuff more readable.
The inline assembly is separated to stand-alone assembler files for MPW's assemblers, using a script.
Shared libraries are supplied for use by all environments.
Routines | Platforms | Using BlitPixie | Prototypes |
The blitters commonly accept a baseAddr which is a pointer to the start of pixel memory, and a rowBytes which is the offset in bytes from one line of pixels to the next. Pointer parameters are declared as unsigned char * (UInt8*), and integer parameters as unsigned long (UInt32).
The blitter routines work in one of the following bit depths:
Bits per pixel | Bytes per pixel | Pointer type | Colors |
---|---|---|---|
8 | 1 | unsigned char | 256 Colors |
16 | 2 | unsigned short | Thousands |
32 | 4 | unsigned long | Millions |
Other pixel depths, such as 1,2,4 or 24 bits are not supported (except with BlitPixieAllBit on the 68k). Pixel conversions are not supported at all.
To access the pixel memory on the 68k, the processor should be put in 32-bit mode (instead of 24-bit mode) if it isn't already and the pixel map so requires. This can be checked by using PixMap32Bit and changed using SwapMMUMode. Or always use 32-bit mode...
For a long time Apple, Inc.'s official position was that drawing directly to the screen in this way is not officially supported, and is not guaranteed to work with future hardware or system software. More recently, Apple has stated that direct-to-screen drawing will continue to be supported by the next generation of system software (System 8), providing certain guidelines are followed. BlitPixie follows those guidelines that are its responsibility; other guidelines are the responsibility of the programmer (you), and are described below.
In general, the major problem with direct-to-screen drawing is simply that it's
difficult to guarantee that it has been done correctly and will work for all end users.
Drawing to the screen is much more sensitive to differences in user's hardware and
system setups than most code, so it's harder to test.
The sprite compiler converts a pixel mask into a set of 68k assembly instructions (returned as a function ptr), that will draw the masked sprite using the image data when you call it.
NOTE: This function obviously performs no clipping, so be careful.
typedef unsigned long TokenDataType; #define kTokenShift 24 #define kCountMask 0x00FFFFFFL
Token | Value | Count | Extra Data |
---|---|---|---|
kEndShapeToken | 00 | always zero | - |
kLineStartToken | 01 | offset to next linestart token | - |
kDrawPixelsToken | 02 | bytes to draw | count bytes of pixel data + 0-3 bytes of padding to align to next 4-byte boundary |
kSkipPixelsToken | 03 | bytes to skip | - |
kSingleColorToken | 04 | bytes to fill | 4 bytes (1/2/4 pixels) to fill repeatedly with |
Example:
kLineStartToken #12 - kSkipPixelsToken #12 - kDrawPixelsToken #8 $FF00FF00FF00FF00 kLineStartToken #16 - kSkipPixelsToken #16 - kDrawPixelsToken #4 $FF00 - kSingleColorToken #20 $0000 - kDrawPixelsToken #4 $FF00 kEndShapeToken #0
Routines | Platforms | Using BlitPixie | Prototypes |
///-------------------------------------------------------------------------------------- // BlitPixieHeader.h // general header for BlitPixie, a collection of fast software blitters ///-------------------------------------------------------------------------------------- #ifndef __BLITPIXIE__ #define __BLITPIXIE__ #include "BlitPixieSystem.h" // various system-dependant type definitions #ifndef BLITPIXIE_DEBUG // remove debugger calls, if not debugging (release code) #undef BLITPIXIE_DEBUGGER #define BLITPIXIE_DEBUGGER(x) #endif /* BLITPIXIE_DEBUG */ #ifndef BLITPIXIE_ASSERT // debugging assertion #define BLITPIXIE_ASSERT(x) if (!(x)) { BLITPIXIE_DEBUGGER("Assertion failed: " #x " (" __FILE__ ")"); } #endif /* BLITPIXIE_ASSERT */ #include "BlitPixieVersion.h" // library version ///-------------------------------------------------------------------------------------- // Type definitions and structs ///-------------------------------------------------------------------------------------- // The following struct is used by BlitPixieDoubleRects. struct BlitPixieOffsetInfo { long srcOffsetAtoB; /* offset from right of rect A to left of rect B */ long srcOffsetBtoA; /* offset from right of rect B to left of rect A, in the next row */ long dstOffsetAtoB; long dstOffsetBtoA; }; typedef struct BlitPixieOffsetInfo BlitPixieOffsetInfo, *BlitPixieOffsetInfoPtr; // which kind of CPU we're running on, see BlitPixieGetProcessorType extern short gBlitPixieProcessorType; // The following is used by the blitters, for optimal performance enum BlitPixieProcessorTypes { kUnknownProcessor = 0, // 68k Processors k68000, k68010, k68020, k68030, k68040, // PPC Processors k601, k603, k604, kG3, kG4 }; ///-------------------------------------------------------------------------------------- // Library functions ///-------------------------------------------------------------------------------------- // get numeric version unsigned long BlitPixieVersion( void ); // get string version void BlitPixieVersionString( char string[BLITPIXIE_VERSION_STRINGLEN] ); // call this function once at startup void BlitPixieGetProcessorType(void); ///-------------------------------------------------------------------------------------- // utility functions, for C blitters to use ///-------------------------------------------------------------------------------------- // copy a block of memory, using longwords void BlitPixieMemCopy( unsigned char *dst, unsigned char *src, int bytes); // set a block of memory to a repeated longword value void BlitPixieMemSet( unsigned char *dst, unsigned long value, int bytes ); ///-------------------------------------------------------------------------------------- // Blitters that work in 8-bits, 16-bits, and 32-bits ///-------------------------------------------------------------------------------------- void BlitPixieClear( unsigned char *dstPixel, unsigned long dstRowBytes, unsigned short bytes, unsigned short rows, unsigned long color); void BlitPixieRect( unsigned char *srcPixel, unsigned char *dstPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short bytes, unsigned short rows ); void BlitPixieDoubleRects( unsigned char *src, unsigned char *dst, unsigned short bytesA, unsigned short bytesB, unsigned short rows, BlitPixieOffsetInfo *info ); void BlitPixieBlitClear( unsigned char *src, unsigned char *dst, unsigned long color, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short bytes, unsigned short rows); void BlitPixieBlitErase( unsigned char *src, unsigned char *dst, unsigned char *background, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short bytes, unsigned short rows); void BlitPixieMask( unsigned char *srcPixel, unsigned char *dstPixel, unsigned char *maskPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short bytes, unsigned short rows ); void BlitPixiePartialMask( unsigned char *srcPixel, unsigned char *dstPixel, unsigned char *maskPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short bytes, unsigned short rows ); void BlitPixieMaskColor( unsigned long srcColor, unsigned char *dstPixel, unsigned char *maskPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short bytes, unsigned short rows ); Boolean BlitPixieMaskCollision( unsigned char *maskPtr1, unsigned char *maskPtr2, unsigned long rowBytes1, unsigned long rowBytes2, unsigned short bytes, unsigned short rows ); ///-------------------------------------------------------------------------------------- // Blitters that have different routines for different bit depths ///-------------------------------------------------------------------------------------- void BlitPixieColorKey8Bit( unsigned char *srcPixel, unsigned char *dstPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short bytes, unsigned short rows, unsigned char colorKey); void BlitPixieColorKey16Bit( unsigned short *srcPixel, unsigned short *dstPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short bytes, unsigned short rows, unsigned short colorKey); void BlitPixieColorKey32Bit( unsigned long *srcPixel, unsigned long *dstPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short bytes, unsigned short rows, unsigned long colorKey); void BlitPixieFlip8Bit( unsigned char *srcPixel, unsigned char *dstPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short width, unsigned short height); void BlitPixieFlip16Bit( unsigned short *srcPixel, unsigned short *dstPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short width, unsigned short height); void BlitPixieFlip32Bit( unsigned long *srcPixel, unsigned long *dstPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short width, unsigned short height); void BlitPixieFlipMask8Bit( unsigned char *srcPixel, unsigned char *dstPixel, unsigned char *maskPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short width, unsigned short height); void BlitPixieFlipMask16Bit( unsigned short *srcPixel, unsigned short *dstPixel, unsigned short *maskPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short width, unsigned short height); void BlitPixieFlipMask32Bit( unsigned long *srcPixel, unsigned long *dstPixel, unsigned long *maskPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short width, unsigned short height); Boolean BlitPixieFlipMaskCollision( unsigned char *maskPtr1, unsigned char *maskPtr2, unsigned long rowBytes1, unsigned long rowBytes2, unsigned short bytes, unsigned short rows ); void BlitPixieFlipMaskColor( unsigned long srcColor, unsigned char *dstPixel, unsigned char *maskPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short bytes, unsigned short rows ); void BlitPixieDoubled8Bit( unsigned char *srcPixel, unsigned char *dstPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short width, unsigned short height); void BlitPixieDoubled16Bit( unsigned short *srcPixel, unsigned short *dstPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short width, unsigned short height); void BlitPixieDoubled32Bit( unsigned long *srcPixel, unsigned long *dstPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned short width, unsigned short height); void BlitPixieScale8Bit( unsigned char *src, unsigned long srcBytes, long width1, long height1, long startu, unsigned char *dst, unsigned long dstBytes, long width2, long height2, long startv ); void BlitPixieScaleMask8Bit( unsigned char *src, unsigned long srcBytes, long width1, long height1, long startu, unsigned char *dst, unsigned long dstBytes, long width2, long height2, long startv, unsigned char *mask ); void BlitPixieScale16Bit( unsigned short *src, unsigned long srcBytes, long width1, long height1, long startu, unsigned short *dst, unsigned long dstBytes, long width2, long height2, long startv ); void BlitPixieScaleMask16Bit( unsigned short *src, unsigned long srcBytes, long width1, long height1, long startu, unsigned short *dst, unsigned long dstBytes, long width2, long height2, long startv, unsigned short *mask ); void BlitPixieScale32Bit( unsigned long *src, unsigned long srcBytes, long width1, long height1, long startu, unsigned long *dst, unsigned long dstBytes, long width2, long height2, long startv ); void BlitPixieScaleMask32Bit( unsigned long *src, unsigned long srcBytes, long width1, long height1, long startu, unsigned long *dst, unsigned long dstBytes, long width2, long height2, long startv, unsigned long *mask ); void BlitPixieRotoZoom8Bit( unsigned char *srcPixel, unsigned char *dstPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned long width1, unsigned long height1, unsigned long width2, unsigned long height2, unsigned long angle, unsigned long zoom ); void BlitPixieMaskRotoZoom8Bit( unsigned char *srcPixel, unsigned char *dstPixel, unsigned char *maskPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned long width1, unsigned long height1, unsigned long width2, unsigned long height2, unsigned long angle, unsigned long zoom ); void BlitPixieRotoZoom16Bit( unsigned short *srcPixel, unsigned short *dstPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned long width1, unsigned long height1, unsigned long width2, unsigned long height2, unsigned long angle, unsigned long zoom ); void BlitPixieMaskRotoZoom16Bit( unsigned short *srcPixel, unsigned short *dstPixel, unsigned short *maskPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned long width1, unsigned long height1, unsigned long width2, unsigned long height2, unsigned long angle, unsigned long zoom ); void BlitPixieRotoZoom32Bit( unsigned long *srcPixel, unsigned long *dstPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned long width1, unsigned long height1, unsigned long width2, unsigned long height2, unsigned long angle, unsigned long zoom ); void BlitPixieMaskRotoZoom32Bit( unsigned long *srcPixel, unsigned long *dstPixel, unsigned long *maskPixel, unsigned long srcRowBytes, unsigned long dstRowBytes, unsigned long width1, unsigned long height1, unsigned long width2, unsigned long height2, unsigned long angle, unsigned long zoom ); ///-------------------------------------------------------------------------------------- // zero-overdraw dirty rect screen blitter, works in 8-bits, 16-bits, and 32-bits ///-------------------------------------------------------------------------------------- Boolean BlitPixieInitDirtyRects( unsigned char *src, unsigned char *dst, unsigned short width, unsigned short height, unsigned short depth); void BlitPixieAddDirtyRect( Rect *dirtyRect ); void BlitPixieClearDirtyRects(void); void BlitPixieExitDirtyRects(void); void BlitPixieBlitClearDirtyRects( unsigned char *src, unsigned char *dst, unsigned long color, unsigned long srcRowBytes, unsigned long dstRowBytes); void BlitPixieBlitEraseDirtyRects( unsigned char *src, unsigned char *dst, unsigned char *background, unsigned long srcRowBytes, unsigned long dstRowBytes); ///-------------------------------------------------------------------------------------- // pre-generated RLE tokens blitter, works in 8-bits, 16-bits, and 32-bits ///-------------------------------------------------------------------------------------- #define BLITPIXIE_USE_DRAW_SPANS 1 // whether to use spans of single color ? typedef unsigned long TokenDataType, *TokenDataPtr, **TokenDataHdl; #define kTokenShift 24 #define kCountMask 0x00FFFFFFL #define kEndShapeToken 0x00L #define kLineStartToken 0x01L #define kDrawPixelsToken 0x02L #define kSkipPixelsToken 0x03L #if BLITPIXIE_USE_DRAW_SPANS #define kSingleColorToken 0x04L // (this token not used in the original code) #endif void BlitPixieRLE( unsigned char *srcTokens, unsigned char *dstPixel, unsigned long dstRowBytes); void BlitPixieRLEClipped( unsigned char *srcTokens, unsigned char *dstPixel, unsigned long dstOffset, Rect *dstClipRect); void BlitPixieRLEColor( unsigned char *srcTokens, unsigned long srcColor, unsigned char *dstPixel, unsigned long dstRowBytes); void BlitPixieRLEColorClipped( unsigned char *srcTokens, unsigned long srcColor, unsigned char *dstPixel, unsigned long dstRowBytes, Rect *dstClipRect ); Boolean BlitPixieRLECollision( unsigned char *srcTokens, unsigned char *dstTokens, Rect *srcRect, Rect *dstRect); #ifdef macintosh // on the Macintosh, the compiler returns a handle from "NewHandle" OSErr BlitPixieRLEParsePixels( unsigned char *srcStartAddrP, unsigned char *maskStartAddrP, unsigned long rowBytes, unsigned short width, unsigned short height, unsigned short depth, TokenDataHdl *newPixCodeH); #else // on other systems, the compiler returns a pointer from "malloc" int BlitPixieRLEParsePixels( unsigned char *srcStartAddrP, unsigned char *maskStartAddrP, unsigned long rowBytes, unsigned short width, unsigned short height, unsigned short depth, TokenDataPtr *newPixCodeP); #endif /* macintosh */ ///-------------------------------------------------------------------------------------- // 68k blitter that works in depths below 8 bits per pixel too (i.e. in : 1,2,4,8,16,32) ///-------------------------------------------------------------------------------------- #if defined(macintosh) && GENERATING68K void BlitPixieAllBitRect( register unsigned char *srcPixelP, register unsigned char *dstPixelP, register unsigned long srcRowBytes, register unsigned long dstRowBytes, unsigned long numBytesPerRow, unsigned long rowsToCopy, register unsigned long srcExtraStart, register unsigned long dstExtraStart, register unsigned long dstExtraEnd); void BlitPixieAllBitMask( register unsigned char *srcPixelP, register unsigned char *dstPixelP, register unsigned char *maskPixelP, register unsigned long srcRowBytes, register unsigned long dstRowBytes, unsigned long numBytesPerRow, unsigned long rowsToCopy, register unsigned long srcExtraStart, register unsigned long dstExtraStart, register unsigned long dstExtraEnd); void BlitPixieAllBitPartialMask( register unsigned char *srcPixelP, register unsigned char *dstPixelP, register unsigned char *maskPixelP, register unsigned long srcRowBytes, register unsigned long dstRowBytes, unsigned long numBytesPerRow, unsigned long rowsToCopy, register unsigned long srcExtraStart, register unsigned long dstExtraStart, register unsigned long dstExtraEnd); #endif /* GENERATING68K */ ///-------------------------------------------------------------------------------------- // sprite compiler for 68k code, works in 8-bits, 16-bits, and 32-bits ///-------------------------------------------------------------------------------------- #if defined(macintosh) && GENERATING68K // blitter requires a pointer to external pixel data (only mask in code) // this compiled blitter does NOT handle ANY clipping! // use BlitPixieMask for that (which requires a pixel mask). typedef void (*BlitFuncPtr)( long srcRowBytes, long dstRowBytes, char *srcBaseAddr, char *dstBaseAddr); typedef BlitFuncPtr *PixelCodeHdl; OSErr BlitPixieCodeParsePixels( unsigned char *maskStartAddrP, unsigned long rowBytes, unsigned short numBytesPerScanLine, unsigned short numberOfScanLines, PixelCodeHdl* newPixCodeH); #endif /* GENERATING68K */ ///--------------------------------------------------------------------------------------
Routines | Platforms | Using BlitPixie | Prototypes |
Last updated on 00-03-11 by afb.