home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************************************
- * DXSurfB.cpp *
- *------------*
- * Description:
- * This module contains the CDXBaseSurface implementaion.
- *-------------------------------------------------------------------------------
- * Created By: RAL Date: 02/12/1998
- * Copyright (C) 1998 Microsoft Corporation
- * All Rights Reserved
- *
- *-------------------------------------------------------------------------------
- * Revisions:
- *
- *******************************************************************************/
- //--- Additional includes
- #include "stdafx.h"
- #include <DXTrans.h>
- #include "DXSurfB.h"
- #include "new.h"
-
- CDXBaseSurface::CDXBaseSurface() :
- m_ulLocks(0),
- m_ulThreadsWaiting(0),
- m_Height(0),
- m_Width(0),
- m_pFreePtr(NULL),
- m_dwStatusFlags(DXSURF_READONLY),
- m_dwAppData(0)
- {
- m_hSemaphore = CreateSemaphore(NULL, 0, MAXLONG, NULL);
- m_ulNumInRequired = m_ulMaxInputs = 0;
- }
-
- HRESULT CDXBaseSurface::FinalConstruct()
- {
- return m_hSemaphore ? S_OK : E_OUTOFMEMORY;
- }
-
- void CDXBaseSurface::FinalRelease()
- {
- while (m_pFreePtr)
- {
- CDXBaseARGBPtr *pNext = m_pFreePtr->m_pNext;
- DeleteARGBPointer(m_pFreePtr);
- m_pFreePtr = pNext;
- }
- if (m_hSemaphore)
- {
- CloseHandle(m_hSemaphore);
- }
- }
-
- STDMETHODIMP CDXBaseSurface::GetGenerationId(ULONG *pGenerationId)
- {
- if (DXIsBadWritePtr(pGenerationId, sizeof(*pGenerationId)))
- {
- return E_POINTER;
- }
- Lock();
- OnUpdateGenerationId();
- *pGenerationId = m_dwGenerationId;
- Unlock();
- return S_OK;
- }
-
- STDMETHODIMP CDXBaseSurface::IncrementGenerationId(BOOL /*bRefresh */)
- {
- Lock();
- m_dwGenerationId++;
- Unlock();
- return S_OK;
- }
-
-
- STDMETHODIMP CDXBaseSurface::GetObjectSize(ULONG *pcbSize)
- {
- HRESULT hr = S_OK;
- if (DXIsBadWritePtr(pcbSize, sizeof(*pcbSize)))
- {
- hr = E_POINTER;
- }
- else
- {
- Lock();
- *pcbSize = OnGetObjectSize();
- Unlock();
- }
- return hr;
- }
-
- STDMETHODIMP CDXBaseSurface::MapBoundsIn2Out
- (const DXBNDS *pInBounds, ULONG ulNumInBnds, ULONG /*ulOutIndex*/, DXBNDS *pOutBounds)
- {
- HRESULT hr = S_OK;
- if (DXIsBadWritePtr(pOutBounds, sizeof(*pOutBounds)))
- {
- hr = E_POINTER;
- }
- else
- {
- Lock();
- new(pOutBounds) CDXDBnds(m_Width, m_Height);
- Unlock();
- }
- return hr;
- }
-
- STDMETHODIMP CDXBaseSurface::InitSurface(IUnknown *pDirectDraw,
- const DDSURFACEDESC * pDDSurfaceDesc,
- const GUID * pFormatId,
- const DXBNDS *pBounds,
- DWORD dwFlags)
- {
- HRESULT hr = S_OK;
- if (pDDSurfaceDesc || DXIsBadReadPtr(pBounds, sizeof(*pBounds)) || pBounds->eType != DXBT_DISCRETE)
- {
- hr = E_INVALIDARG;
- }
- else
- {
- _EnterCritWith0PtrLocks();
- if (m_Width)
- {
- hr = HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
- }
- else
- {
- CDXDBnds *pbnds = (CDXDBnds *)pBounds;
- hr = OnSetSize(pbnds->Width(), pbnds->Height());
- }
- Unlock();
- }
- return hr;
- }
-
-
- STDMETHODIMP CDXBaseSurface::GetPixelFormat(GUID *pFormat, DXSAMPLEFORMATENUM *pSampleFormatEnum)
- {
- HRESULT hr = S_OK;
- if (DX_IS_BAD_OPTIONAL_WRITE_PTR(pFormat) ||
- DX_IS_BAD_OPTIONAL_WRITE_PTR(pSampleFormatEnum))
- {
- hr = E_POINTER;
- }
- else
- {
- if (pFormat) *pFormat = SurfaceCLSID();
- if (pSampleFormatEnum) *pSampleFormatEnum = SampleFormatEnum();
- }
- return hr;
- }
-
- STDMETHODIMP CDXBaseSurface::GetBounds(DXBNDS* pBounds)
- {
- HRESULT hr = S_OK;
- if (DXIsBadWritePtr(pBounds, sizeof(*pBounds)))
- {
- hr = E_POINTER;
- }
- else
- {
- Lock();
- new(pBounds) CDXDBnds(m_Width, m_Height);
- Unlock();
- }
- return hr;
- }
-
- STDMETHODIMP CDXBaseSurface::GetStatusFlags(DWORD* pdwStatusFlags)
- {
- HRESULT hr = S_OK;
- if (DXIsBadWritePtr(pdwStatusFlags, sizeof(*pdwStatusFlags)))
- {
- hr = E_POINTER;
- }
- else
- {
- Lock();
- *pdwStatusFlags = m_dwStatusFlags;
- Unlock();
- }
- return hr;
- }
-
- STDMETHODIMP CDXBaseSurface::SetStatusFlags(DWORD dwStatusFlags )
- {
- _EnterCritWith0PtrLocks();
- // BUGBUG -- Think about this
- m_dwStatusFlags = dwStatusFlags | DXSURF_READONLY;
- m_dwGenerationId++;
- Unlock();
- return S_OK;
- }
-
- STDMETHODIMP CDXBaseSurface::GetDirectDrawSurface(REFIID riid, void **ppSurface)
- {
- return E_NOTIMPL;
- }
-
- STDMETHODIMP CDXBaseSurface::LockSurface(const DXBNDS *pBounds, ULONG ulTimeOut,
- DWORD dwFlags, REFIID riid, void **ppPointer,
- DWORD * pGenerationId)
- {
- HRESULT hr = S_OK;
- BOOL bMPLockOnly = m_bInMultiThreadWorkProc;
-
- if (!bMPLockOnly) Lock();
- m_MPWorkProcCrit.Lock();
-
- if (m_Width == 0)
- {
- hr = E_FAIL; // BUGBUG -- What code??
- }
- else
- {
- RECT r;
- r.top = r.left = 0;
- r.right = m_Width;
- r.bottom = m_Height;
- if (pBounds)
- {
- if (pBounds->eType != DXBT_DISCRETE)
- {
- hr = DXTERR_INVALID_BOUNDS;
- }
- else
- {
- ((CDXDBnds *)pBounds)->GetXYRect(r);
- if (r.top < 0 || r.left < 0 || (ULONG)r.right > m_Width || (ULONG)r.bottom > m_Height || r.bottom <= r.top || r.right <= r.left)
- {
- hr = DXTERR_INVALID_BOUNDS;
- }
- }
- }
- if (SUCCEEDED(hr))
- {
- CDXBaseARGBPtr * pPtr = m_pFreePtr;
- if (pPtr)
- {
- m_pFreePtr = pPtr->m_pNext;
- }
- else
- {
- hr = CreateARGBPointer(this, &pPtr);
- }
- if (SUCCEEDED(hr))
- {
- hr = pPtr->InitFromLock(r, ulTimeOut, dwFlags, riid, ppPointer);
- if (pGenerationId)
- {
- if (DXIsBadWritePtr(pGenerationId, sizeof(*pGenerationId)))
- {
- hr = E_POINTER;
- }
- else
- {
- *pGenerationId = m_dwGenerationId;
- }
- }
- if (SUCCEEDED(hr))
- {
- m_ulLocks++;
- }
- else
- {
- pPtr->m_pNext = m_pFreePtr;
- m_pFreePtr = pPtr;
- }
- }
- }
- }
- m_MPWorkProcCrit.Unlock();
- if (!bMPLockOnly) Unlock();
- return hr;
- }
-
- void CDXBaseSurface::_InternalUnlock(CDXBaseARGBPtr *pPtrToUnlock)
- {
- BOOL bMPLockOnly = m_bInMultiThreadWorkProc;
-
- if (!bMPLockOnly) Lock();
- m_MPWorkProcCrit.Lock();
- pPtrToUnlock->m_pNext = m_pFreePtr;
- m_pFreePtr = pPtrToUnlock;
- m_ulLocks--;
- if ((m_ulLocks == 0) && m_ulThreadsWaiting)
- {
- ReleaseSemaphore(m_hSemaphore, m_ulThreadsWaiting, NULL);
- m_ulThreadsWaiting = 0;
- }
- m_MPWorkProcCrit.Unlock();
- if (!bMPLockOnly) Unlock();
-
- IUnknown *punkOuter = GetControllingUnknown();
- punkOuter->Release(); // Release pointer's reference to us
- // which could kill us! Don't touch
- // any members after this point.
- }
-
- //
- // Picking interface needs to test the appropriate point for hit testing
- //
- HRESULT CDXBaseSurface::OnSurfacePick(const CDXDBnds & OutPoint, ULONG & ulInputIndex, CDXDVec & InVec)
- {
- HRESULT hr;
- IDXARGBReadPtr *pPtr;
- hr = LockSurface(&OutPoint, m_ulLockTimeOut, DXLOCKF_READ,
- IID_IDXARGBReadPtr, (void **)&pPtr, NULL);
- if( SUCCEEDED(hr) )
- {
- DXPMSAMPLE val;
- pPtr->UnpackPremult(&val, 1, FALSE);
- pPtr->Release();
- hr = val.Alpha ? DXT_S_HITOUTPUT : S_FALSE;
- }
- else
- {
- if (hr == DXTERR_INVALID_BOUNDS) hr = S_FALSE;
- }
- return hr;
- }
-
- /*****************************************************************************
- * RegisterSurface (STATIC member function)
- *-----------------------------------------------------------------------------
- * Description:
- *-----------------------------------------------------------------------------
- * Created By: RAL Date: 12/10/97
- *-----------------------------------------------------------------------------
- * Parameters:
- *****************************************************************************/
- HRESULT CDXBaseSurface::
- RegisterSurface(REFCLSID rcid, int ResourceId, ULONG cCatImpl, const CATID * pCatImpl,
- ULONG cCatReq, const CATID * pCatReq, BOOL bRegister)
- {
- HRESULT hr = bRegister ? _Module.UpdateRegistryFromResource(ResourceId, bRegister) : S_OK;
- if (SUCCEEDED(hr))
- {
- CComPtr<ICatRegister> pCatRegister;
- HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_ALL, IID_ICatRegister, (void **)&pCatRegister);
- if (SUCCEEDED(hr))
- {
- if (bRegister)
- {
- hr = pCatRegister->RegisterClassImplCategories(rcid, cCatImpl, (CATID *)pCatImpl);
- if (SUCCEEDED(hr) && cCatReq && pCatReq) {
- hr = pCatRegister->RegisterClassReqCategories(rcid, cCatReq, (CATID *)pCatReq);
- }
- }
- else
- {
- pCatRegister->UnRegisterClassImplCategories(rcid, cCatImpl, (CATID *)pCatImpl);
- if (cCatReq && pCatReq)
- {
- pCatRegister->UnRegisterClassReqCategories(rcid, cCatReq, (CATID *)pCatReq);
- }
- }
- }
- }
- if ((!bRegister) && SUCCEEDED(hr))
- {
- _Module.UpdateRegistryFromResource(ResourceId, bRegister);
- }
- return hr;
- }
-
- //
- // CDXBaseARGBPtr
- //
- STDMETHODIMP CDXBaseARGBPtr::QueryInterface(REFIID riid, void ** ppv)
- {
- if (IsEqualGUID(riid, IID_IUnknown) ||
- IsEqualGUID(riid, IID_IDXARGBReadPtr))
- {
- *ppv = (IDXARGBReadPtr *)this;
- m_ulRefCount++;
- return S_OK;
- }
- else
- {
- *ppv = NULL;
- return E_NOINTERFACE;
- }
- }
-
-
- ULONG STDMETHODCALLTYPE CDXBaseARGBPtr::AddRef()
- {
- return ++m_ulRefCount;
- }
-
- ULONG STDMETHODCALLTYPE CDXBaseARGBPtr::Release()
- {
- --m_ulRefCount;
- ULONG c = m_ulRefCount;
- if (c == 0)
- {
- m_pSurface->_InternalUnlock(this); // Don't touch members after this call.
- }
- return c;
- }
-
- HRESULT STDMETHODCALLTYPE CDXBaseARGBPtr::GetSurface(REFIID riid, void **ppSurface)
- {
- return m_pSurface->GetControllingUnknown()->QueryInterface(riid, ppSurface);
- }
-
-
- DXSAMPLEFORMATENUM STDMETHODCALLTYPE CDXBaseARGBPtr::GetNativeType(DXNATIVETYPEINFO *pInfo)
- {
- if (pInfo)
- {
- memset(pInfo, 0, sizeof(pInfo));
- }
- return m_pSurface->SampleFormatEnum();
- }
-
-
- void STDMETHODCALLTYPE CDXBaseARGBPtr::Move(long cSamples)
- {
- m_FillInfo.x += cSamples;
- //--- Moving one column past the end is okay
- _ASSERT((long)m_FillInfo.x <= m_LockedRect.right);
- }
-
- void STDMETHODCALLTYPE CDXBaseARGBPtr::MoveToRow(ULONG y)
- {
- m_FillInfo.x = m_LockedRect.left;
- m_FillInfo.y = y + m_LockedRect.top;
- _ASSERT((long)m_FillInfo.y < m_LockedRect.bottom);
- }
-
- void STDMETHODCALLTYPE CDXBaseARGBPtr::MoveToXY(ULONG x, ULONG y)
- {
- m_FillInfo.x = x + m_LockedRect.left;
- m_FillInfo.y = y + m_LockedRect.top;
- //--- Moving one column past the end is okay
- _ASSERT((long)m_FillInfo.x <= m_LockedRect.right);
- _ASSERT((long)m_FillInfo.y < m_LockedRect.bottom);
- }
-
- ULONG STDMETHODCALLTYPE CDXBaseARGBPtr::MoveAndGetRunInfo(ULONG Row, const DXRUNINFO ** ppInfo)
- {
- m_FillInfo.x = m_LockedRect.left;
- m_FillInfo.y = Row + m_LockedRect.top;
- _ASSERT((long)m_FillInfo.y < m_LockedRect.bottom);
- *ppInfo = &m_RunInfo;
- return 1;
- }
-
- DXSAMPLE *STDMETHODCALLTYPE CDXBaseARGBPtr::Unpack(DXSAMPLE *pSamples, ULONG cSamples, BOOL bMove)
- {
- m_FillInfo.pSamples = pSamples;
- m_FillInfo.cSamples = cSamples;
- m_FillInfo.bPremult = false;
- FillSamples(m_FillInfo);
- if (bMove) m_FillInfo.x += cSamples;
- return pSamples;
- }
-
- DXPMSAMPLE *STDMETHODCALLTYPE CDXBaseARGBPtr::UnpackPremult(DXPMSAMPLE *pSamples, ULONG cSamples, BOOL bMove)
- {
- m_FillInfo.pSamples = pSamples;
- m_FillInfo.cSamples = cSamples;
- m_FillInfo.bPremult = true;
- FillSamples(m_FillInfo);
- if (bMove) m_FillInfo.x += cSamples;
- return pSamples;
- }
-
- void STDMETHODCALLTYPE CDXBaseARGBPtr::UnpackRect(const DXPACKEDRECTDESC *pDesc)
- {
- DXPtrFillInfo FillInfo;
- FillInfo.pSamples = pDesc->pSamples;
- FillInfo.cSamples = pDesc->rect.right - pDesc->rect.left;
- FillInfo.x = pDesc->rect.left + m_LockedRect.left;
- FillInfo.bPremult = pDesc->bPremult;
- ULONG YLimit = pDesc->rect.bottom + m_LockedRect.top;
- for (FillInfo.y = pDesc->rect.top + m_LockedRect.top;
- FillInfo.y < YLimit;
- FillInfo.y++)
- {
- FillSamples(FillInfo);
- FillInfo.pSamples += FillInfo.cSamples;
- }
- }
-
- HRESULT CDXBaseARGBPtr::InitFromLock(const RECT & rect, ULONG /*ulTimeOut*/, DWORD dwLockFlags, REFIID riid, void ** ppv)
- {
- HRESULT hr = S_OK;
- if (dwLockFlags & DXLOCKF_READWRITE)
- {
- hr = E_INVALIDARG;
- }
- else
- {
- m_LockedRect = rect;
- m_RunInfo.Count = rect.right - rect.left;
- if (m_pSurface->SampleFormatEnum() & DXPF_TRANSPARENCY)
- {
- m_RunInfo.Type = DXRUNTYPE_UNKNOWN;
- }
- else
- {
- m_RunInfo.Type = DXRUNTYPE_OPAQUE;
- }
- m_FillInfo.x = rect.left;
- m_FillInfo.y = rect.top;
- hr = QueryInterface(riid, ppv);
- if (SUCCEEDED(hr))
- {
- m_pSurface->GetControllingUnknown()->AddRef();
- }
- }
- return hr;
- }
-