|
|
/******************************Module*Header*******************************\
* Module Name: wndobj.hxx * * Window object. Created for those drivers that want to track changes * in the client region. * * Created: 27-Sep-1993 15:30:05 * Author: Wendy Wu [wendywu] * * Copyright (c) 1993-1999 Microsoft Corporation \**************************************************************************/
#define WO_NOTIFIED 0x80000000
#define WO_NEW_WNDOBJ 0x40000000
#define WO_SURFACE 0x20000000
#define WO_HSEM_OWNER 0x10000000
#define WO_GENERIC_WNDOBJ 0x08000000
#define WO_NEED_DRAW_NOTIFY 0x04000000
#define WO_SPRITE_OVERLAP 0x02000000 // At least one sprite overlaps
// the window area
#define WO_NOSPRITES 0x01000000 // Don't draw any sprites on
// top of this window
// Internal flag allowed in TRACKOBJ.fl and EWNDOBJ.fl (moved to wglp.h)
#define WO_INTERNAL_VALID_FLAGS (WO_NOTIFIED | \
WO_NEW_WNDOBJ | \ WO_SURFACE | \ WO_HSEM_OWNER | \ WO_NEED_DRAW_NOTIFY | \ WO_SPRITE_OVERLAP | \ WO_NOSPRITES)
#define WO_VALID_FLAGS (WO_RGN_CLIENT_DELTA | \
WO_RGN_CLIENT | \ WO_RGN_SURFACE_DELTA | \ WO_RGN_SURFACE | \ WO_RGN_UPDATE_ALL | \ WO_RGN_WINDOW | \ WO_RGN_DESKTOP_COORD | \ WO_GENERIC_WNDOBJ | \ WO_DRAW_NOTIFY | \ WO_SPRITE_NOTIFY)
// TRACKOBJ and EWNDOBJ identifiers
#define TRACKOBJ_IDENTIFIER 0x43415254 // 'TRAC'
#define EWNDOBJ_IDENTIFIER 0x444E5745 // 'EWND'
// Global that indicates whether to notify driver with the new WNDOBJ
// states following a WNDOBJ creation. User has not changed the window
// states but this is required to initialize the driver. The update is
// done in the parent gdi functions (e.g. SetPixelFormat) that allow
// the DDI to create a WNDOBJ.
extern BOOL gbWndobjUpdate;
// Maximum region rectangle
extern RECTL grclMax;
// Global tracking object (TRACKOBJ) pointer.
// If this is non-null, we are tracking some WNDOBJs in the system.
class TRACKOBJ; extern TRACKOBJ* gpto;
#if DBG
#define CHECKUSERCRITIN UserAssertUserCritSecIn()
#define CHECKUSERCRITOUT UserAssertUserCritSecOut()
#else
#define CHECKUSERCRITIN
#define CHECKUSERCRITOUT
#endif
// WINBUG #83114 2-7-2000 bhouse Review and test critical section checks
// We are leaving the critical section checks in place eventhough they may
// no longer work if turned on. At some point during code cleanup we should
// review there use and test.
#if DBG
#if 0
#define CHECKCRITIN(hsem) \
ASSERT((ExIsResourceAcquiredExclusiveLite(hsem) == TRUE) || \ (ExIsResourceAcquiredSharedLite(hsem) == TRUE)) #define CHECKCRITOUT(hsem) \
ASSERT(ExIsResourceAcquiredExclusiveLite(hsem) == FALSE) #else
#define CHECKCRITIN(hsem)
#define CHECKCRITOUT(hsem)
#endif
#define CHECKDEVLOCKIN(dco) \
CHECKCRITIN((dco).hsemDcDevLock) #define CHECKDEVLOCKOUT(dco) \
CHECKCRITOUT((dco).hsemDcDevLock) #define CHECKDEVLOCKIN2(pSurface) \
{ \ PDEVOBJ po((pSurface)->hdev()); \ CHECKCRITIN(po.hsemDevLock()); \ } #define CHECKDEVLOCKOUT2(pSurface) \
{ \ PDEVOBJ po((pSurface)->hdev()); \ CHECKCRITOUT(po.hsemDevLock()); \ } #else
#define CHECKCRITIN(hsem)
#define CHECKCRITOUT(hsem)
#define CHECKDEVLOCKIN(dco)
#define CHECKDEVLOCKOUT(dco)
#define CHECKDEVLOCKIN2(pSurface)
#define CHECKDEVLOCKOUT2(pSurface)
#endif
/******************************Class***************************************\
* class TRACKOBJ * * Each tracking object has a unique driver notification function address * in the pfn field. There is usually one such object per driver although * multiple TRACKOBJs can be created on the same device. For example, a * live video driver may track all live video windows while an OpenGL driver * tracks all OpenGL windows at the same time. The only restriction is * that a window can be tracked by only one TRACKOBJ on the same device. * * The TRACKOBJ points to a linked list of window objects that is being * tracked for a given driver notification function. * * History: * 16-Nov-1993 -by- Wendy Wu [wendywu] * Wrote it. \**************************************************************************/
class TRACKOBJ { public: ULONG ident; TRACKOBJ *ptoNext; EWNDOBJ *pwoSurf; EWNDOBJ *pwo; SURFACE *pSurface; WNDOBJCHANGEPROC pfn; FLONG fl; ERECTL erclSurf;
public: BOOL bValid() { return(ident == TRACKOBJ_IDENTIFIER); }
// Update driver function. fl should not have WOC_RGN_CLIENT_DELTA or
// WOC_RGN_SURFACE_DELTA set.
VOID vUpdateDrv(EWNDOBJ *pwo, FLONG fl) { ASSERTGDI(!(fl & (WOC_RGN_CLIENT_DELTA|WOC_RGN_SURFACE_DELTA)), "TRACKOBJ::vUpdateDrv, Bad flags\n"); (*pfn)((WNDOBJ *)pwo, fl); }
// Update driver function for delta regions. fl must have
// WOC_RGN_CLIENT_DELTA or WOC_RGN_SURFACE_DELTA set.
// Note that if the delta is empty, we do not need to call the driver.
// The compiler does not allow this function to be inline because of forward
// reference.
VOID vUpdateDrvDelta(EWNDOBJ *pwo, FLONG fl); };
typedef TRACKOBJ *PTRACKOBJ;
/******************************Class***************************************\
* class EWNDOBJ * * A EWNDOBJ is a server side window object created by the driver via * EngCreateWnd. It is deleted in GreDeletWnd. * * Once a WNDOBJ is created, a driver may call WNDOBJ_vSetConsumer to * set the pvConsumer field to point to its own window data structure. * * History: * 16-Nov-1993 -by- Wendy Wu [wendywu] * Wrote it. \**************************************************************************/
class EWNDOBJ : public XCLIPOBJ { public: ULONG ident; EWNDOBJ *pwoNext; TRACKOBJ *pto; HWND hwnd; FLONG fl; int ipfd;
// per-WNDOBJ semaphore for generic implementation use only. It is not
// intended for general consumption!
// The surf WNDOBJ does not have a per-WNDOBJ semaphore.
HSEMAPHORE hsem;
public:
BOOL bValid() { return(ident == EWNDOBJ_IDENTIFIER && pto->bValid()); }
VOID vSetClip(REGION *prgn, ERECTL erclClient) { ASSERTGDI(pto->bValid(), "EWNDOBJ::vSetClip: Invalid pto\n");
// Force it to have a non-trivial complexity.
// Otherwise, it will confuse DDI.
vSetup(prgn, *(ERECTL *) &grclMax, CLIP_NOFORCE); rclClient = erclClient;
// If the region is empty, set the complexity to DC_RECT.
if (erclExclude().bEmpty()) iDComplexity = DC_RECT; }
BOOL bDelete() { if (fl & WO_HSEM_OWNER) { ASSERTGDI(hsem, "EWNDOBJ::bDelete: invalid hsem\n"); GreDeleteSemaphore(hsem); }
return XCLIPOBJ::bDeleteRGNOBJ(); // delete RGNOBJ
}
VOID vOffset(LONG x, LONG y); };
typedef EWNDOBJ *PEWNDOBJ;
/******************************Class***************************************\
* class USERCRIT * * The USERCRIT object enters the user vis region critical section. * * When we are updating the TRACKOBJs and WNDOBJs, we want to be in * the user critical section to prevent client regions from changing. * * Note that the user critical section should not be entered if we hold * any of the gdi locks (e.g. devlock). This is to prevent deadlock. * * History: * Thu Jan 13 09:55:23 1994 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
class USERCRIT { private: BOOL bKeep; public: USERCRIT(BOOL bKeepIt = FALSE) { CHECKUSERCRITOUT; UserEnterUserCritSec(); bKeep = bKeepIt; } ~USERCRIT() { if (!bKeep) { CHECKUSERCRITIN; UserLeaveUserCritSec(); CHECKUSERCRITOUT; } } };
/******************************Class***************************************\
* class DEVLOCKOBJ_WNDOBJ * * This class provides a method to get the current WNDOBJ that is associated * with a DCOBJ. * * History: * Thu Jan 13 09:55:23 1994 -by- Hock San Lee [hockl] * Wrote it. \**************************************************************************/
class DEVLOCKOBJ_WNDOBJ : public DEVLOCKOBJ { private: PEWNDOBJ _pwo; BOOL bKeepUserCrit;
public:
// Empty constructor
DEVLOCKOBJ_WNDOBJ() {bKeepUserCrit = TRUE;}
// Constructor - Grab the DEVLOCK and lock down the WNDOBJ.
//
// WARNING: This constructor enters the user critical section temporarily
// to get the current WNDOBJ from user. Therefore, the caller
// should not hold the display devlock prior to this constructor.
VOID vConstructor(XDCOBJ& dco) { // Assume no WNDOBJ.
_pwo = (PEWNDOBJ)NULL;
// Make sure that we don't have devlock before entering user critical
// section. Otherwise, it can cause deadlock.
if (dco.bDisplay() && dco.dctp() == DCTYPE_DIRECT) { CHECKDEVLOCKOUT(dco); }
// Enter user critical section.
USERCRIT usercrit(bKeepUserCrit);
// Grab the devlock.
DEVLOCKOBJ::bLock(dco);
// If it is a display DC, get the pwo that the hdc is associated with.
// If it is a printer or memory DC, get the pwo from pSurface.
if (dco.bDisplay() && dco.dctp() == DCTYPE_DIRECT) { HWND hwnd; if (!UserGetHwnd(dco.hdc(), &hwnd, (PVOID *) &_pwo, FALSE)) { SAVE_ERROR_CODE(ERROR_INVALID_HANDLE); } } else { _pwo = dco.pwo(); } }
DEVLOCKOBJ_WNDOBJ(XDCOBJ& dco, BOOL bKeep = TRUE) { bKeepUserCrit = bKeep; vConstructor(dco); }
// Destructor - Free the DEVLOCK.
~DEVLOCKOBJ_WNDOBJ() { // We need to release devlock then user crit in that order
DEVLOCKOBJ::vDestructorNULL();
if (bKeepUserCrit) { CHECKUSERCRITIN; UserLeaveUserCritSec(); CHECKUSERCRITOUT; } }
// bValidWndobj - Do we have a WNDOBJ for this DC?
BOOL bValidWndobj() { return(_pwo != (PEWNDOBJ)NULL); }
// bValidDevlock - Is the devlock valid?
BOOL bValidDevlock() { return(DEVLOCKOBJ::bValid()); }
// pwo - Get the WNDOBJ pointer for this DC
PEWNDOBJ pwo() { return(_pwo); }
// vInit - Initialize the stack object
VOID vInit() { _pwo = (PEWNDOBJ) NULL;
DEVLOCKOBJ::vInit(); } };
VOID vForceClientRgnUpdate(); VOID vChangeWndObjs(SURFACE*, HDEV, SURFACE*, HDEV); VOID vTransferWndObjs(SURFACE*, HDEV, HDEV);
|