/******************************Module*Header*******************************\ * Module Name: sprite.hxx * * Sprite objects. * * Created: 16-Sep-1997 * Author: J. Andrew Goossen [andrewgo] * * Copyright (c) 1997-1999 Microsoft Corporation * \**************************************************************************/ #ifndef GDIFLAGS_ONLY // used for gdikdx #define DEBUG_SPRITES 0 #define TEXTURE_DEMO 0 #if TEXTURE_DEMO extern HDEV ghdevTextureParent; BOOL TexTexture(VOID*, ULONG); HDC hdcTexture(ULONG); #endif // Function exports to be called from the multi-monitor code: VOID vSpEnableMultiMon(HDEV, ULONG, HDEV*); VOID vSpDisableMultiMon(HDEV); // Functions to handle enabling, disabling, and deletion of sprites: BOOL bSpEnableSprites(HDEV); VOID vSpDisableSprites(HDEV, CLEANUPTYPE = CLEANUP_NONE); VOID vSpDynamicModeChange(HDEV, HDEV); // Tear-down and redraw functions: class EWNDOBJ; VOID vSpHideSprites(HDEV, BOOL); BOOL bSpSpritesVisible(HDEV); BOOL bSpTearDownSprites(HDEV, RECTL*, BOOL = FALSE); VOID vSpUnTearDownSprites(HDEV, RECTL*, BOOL = FALSE); VOID vSpWndobjChange(HDEV, EWNDOBJ*); // SpTextOut should be called in place of EngTextOut, to handle direct // rendering even when a sprite is present: BOOL SpTextOut( SURFOBJ* pso, STROBJ* pstro, FONTOBJ* pfo, CLIPOBJ* pco, RECTL* prclExtra, RECTL* prclOpaque, BRUSHOBJ* pboFore, BRUSHOBJ* pboOpaque, POINTL* pptlOrg, MIX mix); // Duplicate of declaration in alphablt.hxx: class EBLENDOBJ : public _BLENDOBJ { public: XLATEOBJ *pxloSrcTo32; XLATEOBJ *pxloDstTo32; XLATEOBJ *pxlo32ToDst; }; // Global variable that defines a (0, 0) offset: extern POINTL gptlZero; // Handy forward declarations: class SPRITE; typedef struct _SPRITESTATE SPRITESTATE; typedef struct _METASPRITE METASPRITE; /********************************Struct************************************\ * struct SPRITESCAN * * An 'area' list is analagous to a region, and subdivides the screen * into horizontally-biased adjacent rectangles that describe where * sprites are, and are not. * \**************************************************************************/ typedef struct _SPRITERANGE { LONG xLeft; LONG xRight; SPRITE* pSprite; // NULL if no sprite covers this region } SPRITERANGE; typedef struct _SPRITESCAN { LONG yTop; LONG yBottom; SIZE_T siztScan; // Size of this scan's data SIZE_T siztPrevious; // Size of previous scan's data SPRITERANGE aRange[1]; } SPRITESCAN; inline SPRITESCAN* pSpNextScan( SPRITESCAN* pScan) { return((SPRITESCAN*) ((BYTE*) pScan + pScan->siztScan)); } inline SPRITESCAN* pSpPreviousScan( SPRITESCAN* pScan) { return((SPRITESCAN*) ((BYTE*) pScan - pScan->siztPrevious)); } inline SPRITERANGE* pSpLastRange( SPRITESCAN* pScan) { return(((SPRITERANGE*) ((BYTE*) pScan + pScan->siztScan)) - 1); } /*********************************Class************************************\ * class SPRITE * * Identifies a sprite and contains all the information relevant to it. * \**************************************************************************/ #endif // GDIFLAGS_ONLY used for gdikdx #define SPRITE_FLAG_CLIPPING_OBSCURED 0x0001 // Sprite is completely // obscured by clipping #define SPRITE_FLAG_JUST_TRANSFERRED 0x0002 // Used for vSpDynamicModeChange // to denote a sprite that has // already been handled #define SPRITE_FLAG_NO_WINDOW 0x0004 // Marks the meta-sprite for // deletion in low memory // mode changes, when user // unsets the layered flag // on a window #define SPRITE_FLAG_EFFECTIVELY_OPAQUE 0x0008 // Sprite is to be drawn as // opaque, even if ULW_OPAQUE // isn't specified #define SPRITE_FLAG_HIDDEN 0x0010 // Sprite is hidden #define SPRITE_FLAG_VISIBLE 0x0020 // Sprite is visible (counted // in SPRITESTATE::cVisible) // Private define for cursors. Watch out for overlap with the // other ULW_ private defines in gre.h (like ULW_NOREPAINT)! #define ULW_CURSOR 0x04000000 #define ULW_DRAGRECT 0x02000000 #if ((ULW_CURSOR | ULW_DRAGRECT) & (ULW_VALID | ULW_NOREPAINT)) #error ULW_ flags overlap! Must fix! #endif #ifndef GDIFLAGS_ONLY // used for gdikdx typedef struct _SpriteCachedAttributes{ // Cached attributes for sprite ULONG dwShape; // Shape as specified by ULW_ flags BLENDFUNCTION bf; // Alpha value COLORREF crKey; // Color key (transparent color) } SpriteCachedAttributes; class SPRITE { public: FLONG fl; // Miscellaneous SPRITE_FLAG flags DWORD dwShape; // Shape as specified by flags in // UpdateLayeredWindow, plus // miscellaneous SPRITE_FLAG flags METASPRITE* pMetaSprite; // Points to the corresponding meta // sprite when running multi-mon SPRITESTATE* pState; // Points to PDEV related sprite state SPRITE* pNextZ; // Next sprite, bottom-most to top-most SPRITE* pNextY; // Next sprite, in increasing 'y' SPRITE* pPreviousY; // Previous sprite, in decreasing 'y' SPRITE* pNextActive; // Next sprite in active list #if DEBUG_SPRITES SPRITE* pNextVisible; // Next visible sprite #endif ULONG z; // Sprite z-order, starting at 0 with the // backmost sprite HWND hwnd; // Associated window RECTL rclSprite; // Bounds of sprite on the screen, taking // into account any transformations. // This is the effective 'current' size // of the underlay-buffer. For // both US_TRANSFORM_TRANSLATE and // US_TRANSFORM_SCALE, this is also the // destination rectangle. RECTL rclSrc; // Sprite's source rectangle SURFOBJ* psoMask; // Masks surface, for cursor sprites // (will be NULL if not a cursor) SURFOBJ* psoShape; // Copied and transformed sprite surface POINTL OffShape; // Offtor offset that should be added to // any coordinates before drawing on // this surface PALETTE* ppalShape; // Reference to surface palette of mode // in which sprite was originally created ULONG iModeFormat; // STYPE_ bitmap format of mode in which // sprite was originally created FLONG flModeMasks; // Combined red and blue masks of mode in // which sprite was originally created SURFOBJ* psoUnderlay; // Screen bits that underlay the sprite POINTL OffUnderlay; // Offtor offset that should be added // to any coordinates before drawing on // this surface SIZEL sizlHint; // Sprite size hint supplied at sprite // creation sprite time REGION* prgnClip; // Sprite's clip region (may be NULL) BLENDFUNCTION BlendFunction; // Blend information for US_SHAPE_ALPHA ULONG iTransparent; // Transparent color for US_SHAPE_COLORKEY RECTL rclUnderlay; // Location and size of underlay-buffer. // This always bounds 'rclSprite' POINTL ptlDst; // The most recent destination location that // the application passed us SpriteCachedAttributes cachedAttributes; // Cached attributes for alpha value, // color key, and shape ULONG ulTimeStamp; // When the sprite was last drawn }; /*********************************Class************************************\ * struct METASPRITE * * On a multi-mon system, USER needs to be able to address as a single * entity a sprite that actually exists as separate sprites on each * individual device. * * This structure thus represents the multi-mon meta-sprite object that * references multiple device specific sprites. * \**************************************************************************/ typedef struct _METASPRITE { FLONG fl; // Miscellaneous SPRITE_FLAG flags HWND hwnd; // Associated window METASPRITE* pNext; // Next meta-sprite in list ULONG chSprite; // Size of apSprite array SPRITE* apSprite[1]; // Array of device specific sprites } METASPRITE; /********************************Struct************************************\ * struct SPRITESTATE * * Contains all the device-global sprite state. This is simply kept in * the PDEV. * \**************************************************************************/ typedef struct _SPRITESTATE { HDEV hdev; // Handle back to the PDEV, in case we // forget BOOL bHooked; // TRUE if DDI is currently being hooked SPRITE* pListZ; // z-sorted linked list of sprites, from // bottom-most to top-most SPRITE* pListY; // y-sorted linked list of sprites, from // highest to lowest. SURFOBJ* psoScreen; // Pointer to primary surface RECTL rclScreen; // Dimensions of screen ULONG cVisible; // Count of currently visible sprites #if DEBUG_SPRITES SPRITE* pListVisible; // Tracking for all visible sprites #endif ULONG cMultiMon; // Count of multi-mon devices attached // to this PDEV; zero if this is not // a multi-mon meta PDEV HDEV* ahdevMultiMon; // Points to an array of child HDEVs // when a multi-mon meta PDEV METASPRITE* pListMeta; // List of meta-sprites when a multi-mon // PDEV BOOL bInsideDriverCall; // TRUE if we're currently in the // middle of a Drv call from an // Sp routine. This is so we // catch cases of Sp->Drv->Eng->Sp // calls FLONG flOriginalSurfFlags; // Original psurf->SurfFlags values ULONG iOriginalType; // Original psurf->iType value FLONG flSpriteSurfFlags; // Current psurf->SurfFlag values ULONG iSpriteType; // Current psurf->iType value, will // be STYPE_DEVICE when sprites // are visible ULONG iModeFormat; // STYPE_ bitmap format of current mode FLONG flModeMasks; // Combined red and blue masks of current // mode BOOL bValidRange; // TRUE if 'pRange' is currently valid; // FALSE if it's out-of-date and has to // be re-generated SPRITESCAN* pRange; // Points to the beginning of the sprite // range structure that describes the // screen VOID* pRangeLimit; // Denotes last possible SPRITERANGE that // can be stuck in the buffer (note that // this does NOT point to the last scan // record!) SURFOBJ* psoComposite; // Off-screen composition buffer REGION* prgnUncovered; // Clip region describing portions of desk- // top not covered by sprites REGION* prgnTmp; // Temporary region for constructing a // clip object for drawing calls XCLIPOBJ coTmp; // Corresponding temporary clip object REGION* prgnRectangular; // Temporary region for when we need a // DC_RECT clip object XCLIPOBJ coRectangular; // Corresponding rectangular clip object SURFOBJ* psoHitTest; // 1x1 surface used for hit-testing REGION* prgnUnlocked; // Points to a region describing the areas // of the screen that aren't covered by // DirectDraw locks; NULL if there are // no current DirectDraw screen locks HRGN hrgn; // Handy region for processing // vSpUpdateVisRgn calls // These are for handling software mouse cursors and drag-rectangles when // moving windows and 'Show window contents while dragging' isn't // enabled. SPRITE* pSpriteCursor; // Software cursor sprite LONG xHotCursor; // Software cursor's current hot spot LONG yHotCursor; // Software cursor trail state // pSpriteCursors[0] is always the current cursor SPRITE* pTopCursor; // Top most cursor SPRITE* pBottomCursor; // Cursor lowest in Z order ULONG ulNumCursors; // Number of cursors at top of sprite list ULONG ulTrailTimeStamp; // Last time we did mouse trail maintenance ULONG ulTrailPeriod; // How long between mouse trail maintenance BOOL bHaveDragRect; // TRUE if there's an active dragrect HANDLE ahDragSprite[4]; // Handles to 4 sprites that make up the // dragrect; NULL if no active dragrect ULONG ulDragDimension; // Dimension of dragrect side, in pixels RECTL rclDragClip; // Rectangle to clip dragrect against // These point to the driver's true hooked routines (or the corresponding Eng // equivalent if the driver hasn't hooked that call): PFN_DrvStrokePath pfnStrokePath; PFN_DrvFillPath pfnFillPath; PFN_DrvPaint pfnPaint; PFN_DrvBitBlt pfnBitBlt; PFN_DrvCopyBits pfnCopyBits; PFN_DrvStretchBlt pfnStretchBlt; PFN_DrvTextOut pfnTextOut; PFN_DrvLineTo pfnLineTo; PFN_DrvTransparentBlt pfnTransparentBlt; PFN_DrvAlphaBlend pfnAlphaBlend; PFN_DrvPlgBlt pfnPlgBlt; PFN_DrvGradientFill pfnGradientFill; PFN_DrvSaveScreenBits pfnSaveScreenBits; PFN_DrvStretchBltROP pfnStretchBltROP; PFN_DrvDrawStream pfnDrawStream; } SPRITESTATE; /*********************************Class************************************\ * class ENUMAREAS * * Class for enumerating the horizontally biased rectangles composing the * sprite regions under a rectangle. * \**************************************************************************/ class ENUMAREAS { private: ULONG iDir; // Enumeration direction LONG xBoundsLeft; // Bounds of enumeration LONG yBoundsTop; LONG xBoundsRight; LONG yBoundsBottom; LONG yTop; // Current scan top LONG yBottom; // Current scan bottom SPRITESCAN* pScan; // Current scan SPRITERANGE* pRange; // Current range SPRITESCAN* pScanLayer; // Current scan in 'bEnumLayers' traversal SPRITERANGE* pRangeLayer; // Current range in 'bEnumLayers' traversal BOOL bValidRange; // Have the sprite ranges been recomputed // successfully? public: ENUMAREAS(SPRITESTATE* _pSpriteData, RECTL* prclBounds, ULONG iDirection = CD_RIGHTDOWN); BOOL bValid() {return bValidRange;} BOOL bEnum(SPRITE** ppSprite, RECTL* prcl); BOOL bEnumLayers(SPRITE** ppSprite); VOID vResetLayers(); BOOL bAdvanceToTopMostOpaqueLayer(SPRITE** ppSprite); }; /*********************************Class************************************\ * class ENUMUNCOVERED * * Class for all the uncovered ranges of a sprite-region. * \**************************************************************************/ class ENUMUNCOVERED { private: LONG yBoundsBottom; SPRITESCAN* pScan; SPRITESCAN* pNextScan; SPRITERANGE* pRange; public: ENUMUNCOVERED(SPRITESTATE* pState); BOOL bEnum(RECTL* prcl); }; /*********************************Class************************************\ * class ENUMUNDERLAYS * * Class for enumerating all the sprite underlays and non-sprite underlays * touched by a drawing call. * \**************************************************************************/ class ENUMUNDERLAYS { private: SPRITESTATE* pState; CLIPOBJ* pcoOriginal; // Points to object passed to constructor SURFOBJ* psoOriginal; // Points to object passed to constructor SPRITE* pCurrentSprite; // Current sprite in enumeration RECTL rclBounds; // Copy of the drawing bounds intersected // with the clip bounds RECTL rclSaveBounds; // Saved copy of 'pco->rclBounds', which // we modify CLIPOBJ* pcoClip; // Points to effective clip object BOOL bSpriteTouched; // TRUE if we drew under a sprite BOOL bDone; // TRUE if no more bEnum's needed BOOL bResetSurfFlag; // TRUE if we should reset the SurfFlag // when done public: ENUMUNDERLAYS(SURFOBJ* pso, CLIPOBJ* pco, RECTL* prclDraw); BOOL bEnum(SURFOBJ** ppso, POINTL*, CLIPOBJ** ppco); }; /*********************************Class************************************\ * class SPRITELOCK * * This class is responsible for reseting whatever sprite state is * necessary so that we can call the driver directly, bypassing any sprite * code. * * Must be called with the DEVLOCK already held, because we're * messing with the screen surface. * \***************************************************************************/ class SPRITELOCK { private: SPRITESTATE* pState; BOOL bWasAlreadyInsideDriverCall; public: SPRITELOCK(PDEVOBJ& po); ~SPRITELOCK(); }; /*********************************Class************************************\ * class UNDODESKTOPCOORD * * This class is responsible for converting any WO_RGN_DESKTOP_COORD * WNDOBJs temporarily back to device-relative coordinates. * \***************************************************************************/ class UNDODESKTOPCOORD { EWNDOBJ* pwoUndo; LONG xUndo; LONG yUndo; public: UNDODESKTOPCOORD(EWNDOBJ* pwo, SPRITESTATE* pState); ~UNDODESKTOPCOORD(); }; #endif // GDIFLAGS_ONLY used for gdikdx