/******************************************************************************* * DXSurfB.h * *----------* * Description: * This is the header file for the CDXBaseSurface implementation. It is * used as a base class to implement read-only procedural DXSurfaces. *------------------------------------------------------------------------------- * Created By: RAL Date: 02/12/1998 * Copyright (C) 1998 Microsoft Corporation * All Rights Reserved * *------------------------------------------------------------------------------- * Revisions: * *******************************************************************************/ #ifndef __DXSurfB_H__ #define __DXSurfB_H__ #include "dtbase.h" class CDXBaseSurface; class CDXBaseARGBPtr; class ATL_NO_VTABLE CDXBaseSurface : public CDXBaseNTo1, public IDXSurface, public IDXSurfaceInit { /*=== ATL Setup ===*/ public: BEGIN_COM_MAP(CDXBaseSurface) COM_INTERFACE_ENTRY(IDXSurface) COM_INTERFACE_ENTRY(IDXSurfaceInit) COM_INTERFACE_ENTRY_CHAIN(CDXBaseNTo1) END_COM_MAP() DECLARE_GET_CONTROLLING_UNKNOWN() /*=== Member Data ===*/ public: ULONG m_Height; ULONG m_Width; DWORD m_dwStatusFlags; HANDLE m_hSemaphore; ULONG m_ulLocks; ULONG m_ulThreadsWaiting; CDXBaseARGBPtr *m_pFreePtr; DWORD_PTR m_dwAppData; CComAutoCriticalSection m_MPWorkProcCrit; // See comments in LockSurface for details CDXBaseSurface(); HRESULT FinalConstruct(); void FinalRelease(); // // IDXBaseObject // STDMETHODIMP GetGenerationId(ULONG *pGenId); STDMETHODIMP IncrementGenerationId(BOOL bRefresh); STDMETHODIMP GetObjectSize(ULONG *pulze); // // Overridden methods of DXTransform // STDMETHODIMP MapBoundsIn2Out(const DXBNDS *pInBounds, ULONG ulNumInBnds, ULONG /*ulOutIndex*/, DXBNDS *pOutBounds ); // // IDXSurfaceInit // STDMETHODIMP InitSurface(IUnknown *pDirectDraw, const DDSURFACEDESC * pDDSurfaceDesc, const GUID * pFormatId, const DXBNDS *pBounds, DWORD dwFlags); // // IDXSurface methods // STDMETHODIMP GetPixelFormat(GUID *pFormat, DXSAMPLEFORMATENUM *pSampleEnum); STDMETHODIMP GetBounds(DXBNDS *pBounds); STDMETHODIMP GetStatusFlags(DWORD * pdwStatusFlags); STDMETHODIMP SetStatusFlags(DWORD dwStatusFlags); STDMETHODIMP GetDirectDrawSurface(REFIID riid, void **ppSurface); STDMETHODIMP LockSurface(const DXBNDS *pBounds, ULONG ulTimeOut, DWORD dwFlags, REFIID riid, void **ppPointer, DWORD * pGenerationId); STDMETHODIMP SetAppData(DWORD_PTR dwAppData) { m_dwAppData = dwAppData; return S_OK; } STDMETHODIMP GetAppData(DWORD_PTR *pdwAppData) { if (DXIsBadWritePtr(pdwAppData, sizeof(*pdwAppData))) { return E_POINTER; } *pdwAppData = m_dwAppData; return S_OK; } // // These methods aren't supported by procedural surfaces... // STDMETHODIMP GetColorKey(DXSAMPLE *pColorKey) { return E_NOTIMPL; } STDMETHODIMP SetColorKey(DXSAMPLE pColorKey) { return E_NOTIMPL; } STDMETHODIMP LockSurfaceDC(const DXBNDS *pBounds, ULONG ulTimeOut, DWORD dwFlags, IDXDCLock **ppDXLock) { return E_NOTIMPL; } // // Surfaces should override this. // virtual ULONG OnGetObjectSize(void) { return sizeof(*this); } // // This work procedure can be overridden by the derived class to improve performance // or execution of the transform by directly producing data in large blocks if desired. // virtual HRESULT WorkProc(const CDXTWorkInfoNTo1 & WI, BOOL* pbContinueProcessing) { return DXBitBlt(OutputSurface(), WI.OutputBnds, this, WI.DoBnds, m_dwBltFlags, m_ulLockTimeOut); } // // Pick interface needs to test procedural surface. // virtual HRESULT OnSurfacePick(const CDXDBnds & OutPoint, ULONG & ulInputIndex, CDXDVec & InVec); // // Helper functions // // _EnterCritWith0PtrLocks() // // This function is similar to calling Lock() except that it will wait until there // are no pointers to the surface before returning. This should be used whenever you // are going to change the state of a surface, for example the size or some other // property that the read pointers rely on. // // WARNING: You must be sure that one of the following is true: // 1) The objects critical section has NOT been taken prior to calling this function // or 2) There are no pointers to the surface taken prior to calling this function. // // Case 2 is useful in nested function calls. If the outer function has already used this // function to enter the critical section, then it is OK to use it on the inner nested // function. If the object's lock is taken, but there are outstanding pointers, YOU WILL DEADLOCK! // inline void _EnterCritWith0PtrLocks(void) { while (TRUE) { Lock(); if (m_ulLocks == 0) break; m_ulThreadsWaiting++; Unlock(); WaitForSingleObject(m_hSemaphore, INFINITE); } } // // Virtual functions derived class MUST override // virtual const GUID & SurfaceCLSID() = 0; virtual HRESULT CreateARGBPointer(CDXBaseSurface * pSurface, CDXBaseARGBPtr ** ppPtr) = 0; virtual void DeleteARGBPointer(CDXBaseARGBPtr *pPtr) = 0; // // Class may override this virtual function to return a more accurate enum // for example, no transparency or translucency. // virtual DXSAMPLEFORMATENUM SampleFormatEnum() { return (DXSAMPLEFORMATENUM)(DXPF_NONSTANDARD | DXPF_TRANSPARENCY | DXPF_TRANSLUCENCY); } // // Class may override this virtual function to perform necessary computations // when the size of the surface changes. The base class will only call this // function from InitSurface. You may choose to call it from other interfaces // you implement, for example IDXTScaleOutput. // // This function will be called with the critical section taken and 0 outstanding // surface pointers (_EnterCritWith0PtrLocks). // virtual HRESULT OnSetSize(ULONG Width, ULONG Height) { if (m_Width != Width || m_Height != Height) { m_Width = Width; m_Height = Height; m_dwGenerationId++; } return S_OK; } // // Internal functions for base class // void _InternalUnlock(CDXBaseARGBPtr *pPtrToUnlock); // // Static member function for registering surface // static HRESULT RegisterSurface(REFCLSID rcid, int ResourceId, ULONG cCatImpl, const CATID * pCatImpl, ULONG cCatReq, const CATID * pCatReq, BOOL bRegister); }; struct DXPtrFillInfo { DXBASESAMPLE * pSamples; ULONG cSamples; ULONG x; ULONG y; BOOL bPremult; }; class CDXBaseARGBPtr : public IDXARGBReadPtr { public: CDXBaseARGBPtr * m_pNext; CDXBaseSurface * m_pSurface; ULONG m_ulRefCount; DXPtrFillInfo m_FillInfo; RECT m_LockedRect; DXRUNINFO m_RunInfo; CDXBaseARGBPtr(CDXBaseSurface *pSurface) : m_pSurface(pSurface), m_pNext(NULL), m_ulRefCount(0) {} // // IUnknown // STDMETHODIMP QueryInterface(REFIID riid, void ** ppv); ULONG STDMETHODCALLTYPE AddRef(); ULONG STDMETHODCALLTYPE Release(); // // IDXARGBReadPtr // HRESULT STDMETHODCALLTYPE GetSurface(REFIID riid, void **ppSurface); DXSAMPLEFORMATENUM STDMETHODCALLTYPE GetNativeType(DXNATIVETYPEINFO *pInfo); void STDMETHODCALLTYPE Move(long cSamples); void STDMETHODCALLTYPE MoveToRow(ULONG y); void STDMETHODCALLTYPE MoveToXY(ULONG x, ULONG y); ULONG STDMETHODCALLTYPE MoveAndGetRunInfo(ULONG Row, const DXRUNINFO ** ppInfo); DXSAMPLE *STDMETHODCALLTYPE Unpack(DXSAMPLE *pSamples, ULONG cSamples, BOOL bMove); DXPMSAMPLE *STDMETHODCALLTYPE UnpackPremult(DXPMSAMPLE *pSamples, ULONG cSamples, BOOL bMove); void STDMETHODCALLTYPE UnpackRect(const DXPACKEDRECTDESC *pDesc); // // Virtual function derived class MUST override // virtual void FillSamples(const DXPtrFillInfo & FillInfo) = 0; // // Virtual functions derived class MAY want to override (but you will need to call the base class too) // virtual HRESULT InitFromLock(const RECT & rect, ULONG ulTimeOut, DWORD dwLockFlags, REFIID riid, void ** ppv); }; //=== Macro Definitions ============================================ #define DECLARE_REGISTER_DX_SURFACE(id)\ static HRESULT WINAPI UpdateRegistry(BOOL bRegister) \ { \ CATID cat[2]; \ cat[0] = CATID_DXSurface; \ cat[1] = CATID_DXImageTransform; \ return RegisterSurface(GetObjectCLSID(), (id), 2, cat, 0, NULL, bRegister); \ } #define DECLARE_REGISTER_DX_AUTHORING_SURFACE(id)\ static HRESULT WINAPI UpdateRegistry(BOOL bRegister) \ { \ CATID cat[3]; \ cat[0] = CATID_DXSurface; \ cat[1] = CATID_DXImageTransform; \ cat[2] = CATID_DXAuthoringTransform; \ return RegisterSurface(GetObjectCLSID(), (id), 3, cat, 0, NULL, bRegister); \ } #endif