Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1032 lines
34 KiB

/*========================================================================== *
*
* Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
*
* File: ddcursor.c
* Content: DirectDraw cursor support
* History:
* Date By Reason
* ==== == ======
* 17-Jan-00 kanqiu initial implementation(Kan Qiu)
*
***************************************************************************/
#include "ddrawpr.h"
#include "dxcursor.hpp"
#include "swapchan.hpp"
#define FORMAT_8888_1555(val) \
( ((val & 0x80000000) >> 16) | ((val & 0xF80000) >> 9) | ((val & 0xF800) >> 6) | ((val & 0xF8) >> 3))
#define FORMAT_8888_555(val) \
( ((val & 0xF80000) >> 9) | ((val & 0xF800) >> 6) | ((val & 0xF8) >> 3))
#define FORMAT_8888_565(val) \
( ((val & 0xF80000) >> 8) | ((val & 0xFC00) >> 5) | ((val & 0xF8) >> 3))
#define ISOPAQUE(val) \
( 0xFF000000 == (val & 0xFF000000))
#undef DPF_MODNAME
#define DPF_MODNAME "CCursor::CCursor"
//=============================================================================
// CCursor::CCursor
//
//=============================================================================
CCursor::CCursor(CBaseDevice *pDevice)
{
m_pDevice = pDevice;
m_dwCursorFlags = 0;
m_hCursorDdb = NULL;
m_hFrontSave = NULL;
m_hBackSave = NULL;
m_Width = m_Height = 0;
m_hOsCursor = NULL;
m_hHWCursor = NULL;
m_SavedMouseTrails = 0;
m_xCursor = pDevice->SwapChain()->Width()/2;
m_yCursor = pDevice->SwapChain()->Height()/2;
m_MonitorOrigin.x = m_MonitorOrigin.y = 0;
if ( (!pDevice->SwapChain()->Windowed())
&& (1 < pDevice->Enum()->GetAdapterCount()))
{
HMONITOR hMonitor = pDevice->Enum()->
GetAdapterMonitor(pDevice->AdapterIndex());
if (hMonitor)
{
MONITORINFO MonInfo;
MonInfo.rcMonitor.top = MonInfo.rcMonitor.left = 0;
MonInfo.cbSize = sizeof(MONITORINFO);
InternalGetMonitorInfo(hMonitor, &MonInfo);
m_MonitorOrigin.x = MonInfo.rcMonitor.left;
m_MonitorOrigin.y = MonInfo.rcMonitor.top;
}
}
} // CCursor::CCursor
#undef DPF_MODNAME
#define DPF_MODNAME "CCursor::~CCursor"
//=============================================================================
// CCursor::~CCursor
//
//=============================================================================
CCursor::~CCursor()
{
Destroy();
if (m_hOsCursor)
{
SetCursor(m_hOsCursor);
m_hOsCursor = NULL;
}
}
void
CCursor::Destroy()
{
D3D8_DESTROYSURFACEDATA DestroySurfData;
DestroySurfData.hDD = m_pDevice->GetHandle();
if (m_hCursorDdb)
{
DestroySurfData.hSurface = m_hCursorDdb;
m_pDevice->GetHalCallbacks()->DestroySurface(&DestroySurfData);
m_hCursorDdb = NULL;
}
if (m_hFrontSave)
{
DestroySurfData.hSurface = m_hFrontSave;
m_pDevice->GetHalCallbacks()->DestroySurface(&DestroySurfData);
m_hFrontSave = NULL;
}
if (m_hBackSave)
{
DestroySurfData.hSurface = m_hBackSave;
m_pDevice->GetHalCallbacks()->DestroySurface(&DestroySurfData);
m_hBackSave = NULL;
}
if ( NULL != m_hHWCursor )
{
if ( GetCursor() == m_hHWCursor )
SetCursor(NULL); // turn it off before destroy
if (!DestroyIcon((HICON)m_hHWCursor))
{
DPF_ERR("Destroy Failed to Destroy Old hwcursor Icon");
}
m_hHWCursor = NULL;
if (m_SavedMouseTrails > 1)
{
SystemParametersInfo(SPI_SETMOUSETRAILS,m_SavedMouseTrails,0,0);
m_SavedMouseTrails = 0;
}
}
}
void
CCursor::UpdateRects()
{
if (DDRAWI_CURSORISON & m_dwCursorFlags)
{
if (DDRAWI_CURSORSAVERECT & m_dwCursorFlags)
{
// SetPosition didn't update RECTs, but next Flip will
m_dwCursorFlags &= ~DDRAWI_CURSORSAVERECT;
m_dwCursorFlags |= DDRAWI_CURSORRECTSAVED;
m_CursorRectSave = m_CursorRect;
m_BufferRectSave = m_BufferRect;
}
if (m_xCursor < m_xCursorHotSpot)
{
m_CursorRect.left = m_xCursorHotSpot - m_xCursor;
m_CursorRect.right = m_Width;
m_BufferRect.left = 0;
}
else
{
m_CursorRect.left = 0;
m_BufferRect.left = m_xCursor - m_xCursorHotSpot;
if (m_xCursor + m_Width >
m_pDevice->DisplayWidth() + m_xCursorHotSpot )
{
m_CursorRect.right = m_pDevice->DisplayWidth() + m_xCursorHotSpot
- m_xCursor;
}
else
{
m_CursorRect.right = m_Width;
}
}
m_BufferRect.right = m_BufferRect.left + m_CursorRect.right - m_CursorRect.left;
if (m_yCursor < m_yCursorHotSpot)
{
m_CursorRect.top = m_yCursorHotSpot - m_yCursor;
m_CursorRect.bottom = m_Height;
m_BufferRect.top = 0;
}
else
{
m_CursorRect.top = 0;
m_BufferRect.top = m_yCursor - m_yCursorHotSpot;
if (m_yCursor + m_Height >
m_pDevice->DisplayHeight() + m_yCursorHotSpot )
{
m_CursorRect.bottom = m_pDevice->DisplayHeight() + m_yCursorHotSpot
- m_yCursor;
}
else
{
m_CursorRect.bottom = m_Height;
}
}
m_BufferRect.bottom = m_BufferRect.top + m_CursorRect.bottom - m_CursorRect.top;
}
}
/*
* Hide
*
* Hide the cursor. Restore buffer with saved area
*/
#undef DPF_MODNAME
#define DPF_MODNAME "CCursor::Hide"
HRESULT
CCursor::Hide(HANDLE hSurf)
{
if (!(DDRAWI_CURSORISON & m_dwCursorFlags))
{
return S_OK;
}
D3D8_BLTDATA BltData;
ZeroMemory(&BltData, sizeof BltData);
if (DDRAWI_CURSORRECTSAVED & m_dwCursorFlags)
{
// this Hide Must have been caused by flip
m_dwCursorFlags &= ~DDRAWI_CURSORRECTSAVED;
BltData.rSrc.left = m_CursorRectSave.left;
BltData.rSrc.right = m_CursorRectSave.right;
BltData.rSrc.top = m_CursorRectSave.top;
BltData.rSrc.bottom = m_CursorRectSave.bottom;
BltData.rDest.left = m_BufferRectSave.left;
BltData.rDest.top = m_BufferRectSave.top;
BltData.rDest.right = m_BufferRectSave.right;
BltData.rDest.bottom = m_BufferRectSave.bottom;
}
else
{
BltData.rSrc.left = m_CursorRect.left;
BltData.rSrc.right = m_CursorRect.right;
BltData.rSrc.top = m_CursorRect.top;
BltData.rSrc.bottom = m_CursorRect.bottom;
BltData.rDest.left = m_BufferRect.left;
BltData.rDest.top = m_BufferRect.top;
BltData.rDest.right = m_BufferRect.right;
BltData.rDest.bottom = m_BufferRect.bottom;
}
BltData.hSrcSurface = m_hFrontSave;
BltData.hDestSurface = hSurf;
BltData.hDD = m_pDevice->GetHandle();
BltData.dwFlags = DDBLT_ROP | DDBLT_WAIT;
BltData.bltFX.dwROP = SRCCOPY;
BltData.ddRVal = E_FAIL;
m_pDevice->GetHalCallbacks()->Blt(&BltData);
return BltData.ddRVal;
}
/*
* ShowCursor
*
* Show the cursor. save exclusion area and blt cursor to it
*/
#undef DPF_MODNAME
#define DPF_MODNAME "CCursor::Show"
HRESULT
CCursor::Show(HANDLE hSurf)
{
if (!(DDRAWI_CURSORISON & m_dwCursorFlags))
{
return S_OK;
}
D3D8_BLTDATA BltData;
ZeroMemory(&BltData, sizeof BltData);
UpdateRects();
BltData.rSrc.left = m_BufferRect.left;
BltData.rSrc.right = m_BufferRect.right;
BltData.rSrc.top = m_BufferRect.top;
BltData.rSrc.bottom = m_BufferRect.bottom;
BltData.hSrcSurface = hSurf;
BltData.rDest.left = m_CursorRect.left;
BltData.rDest.top = m_CursorRect.top;
BltData.rDest.right = m_CursorRect.right;
BltData.rDest.bottom = m_CursorRect.bottom;
BltData.hDestSurface = m_hFrontSave;
BltData.hDD = m_pDevice->GetHandle();
BltData.dwFlags = DDBLT_ROP | DDBLT_WAIT;
BltData.bltFX.dwROP = SRCCOPY;
BltData.ddRVal = E_FAIL;
m_pDevice->GetHalCallbacks()->Blt(&BltData);
if (SUCCEEDED(BltData.ddRVal))
{
BltData.rSrc.left = m_CursorRect.left;
BltData.rSrc.right = m_CursorRect.right;
BltData.rSrc.top = m_CursorRect.top;
BltData.rSrc.bottom = m_CursorRect.bottom;
BltData.hSrcSurface = m_hCursorDdb;
BltData.rDest.left = m_BufferRect.left;
BltData.rDest.top = m_BufferRect.top;
BltData.rDest.right = m_BufferRect.right;
BltData.rDest.bottom = m_BufferRect.bottom;
BltData.hDestSurface = hSurf;
BltData.hDD = m_pDevice->GetHandle();
BltData.dwFlags = DDBLT_ROP | DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE;
//always use black as key
BltData.bltFX.ddckSrcColorkey.dwColorSpaceLowValue =
BltData.bltFX.ddckSrcColorkey.dwColorSpaceHighValue = 0;
BltData.bltFX.dwROP = SRCCOPY;
BltData.ddRVal = E_FAIL;
m_pDevice->GetHalCallbacks()->Blt(&BltData);
}
return BltData.ddRVal;
}
void
CCursor::Flip()
{
if (DDRAWI_CURSORISON & m_dwCursorFlags)
{
HANDLE htemp = m_hFrontSave;
m_hFrontSave = m_hBackSave;
m_hBackSave = htemp;
}
}
HCURSOR CreateColorCursor(
UINT xHotSpot,
UINT yHotSpot,
UINT BitmapWidth,
UINT BitmapHeight,
CBaseSurface *pCursorBitmap)
{
UINT Width = (UINT)GetSystemMetrics(SM_CXCURSOR);
UINT Height = (UINT)GetSystemMetrics(SM_CYCURSOR);
ICONINFO iconinfo;
D3DLOCKED_RECT lock;
DWORD *pSourceBitmap;
DWORD *pColorMask;
BYTE *pMonoMask;
HCURSOR hCursor = NULL;
HDC hdcMem = NULL;
HBITMAP hbmANDMask = NULL;
HWND hwndDesktop = NULL;
HBITMAP hbmXORBitmap;
HDC hdcScreen;
static char bmi[sizeof(BITMAPINFO) + (sizeof(RGBQUAD) * 255)];
LPBITMAPINFO pbmi = (LPBITMAPINFO)bmi;
iconinfo.fIcon = FALSE;
iconinfo.xHotspot = xHotSpot*Width/BitmapWidth;
iconinfo.yHotspot = yHotSpot*Height/BitmapHeight;
pMonoMask = new BYTE [Width * Height / 8];
if ( NULL == pMonoMask )
{
DPF_ERR("Out of Memory. Unable to create Cursor");
return NULL;
}
ZeroMemory(pMonoMask, (Width * Height / 8));
pColorMask = new DWORD [Width * Height];
if ( NULL == pColorMask )
{
DPF_ERR("Out of Memory. Unable to CreateCursor");
delete[] pMonoMask;
return NULL;
}
if (FAILED(pCursorBitmap->LockRect(&lock, NULL, 0)))
{
DPF_ERR("Failed to lock pCursorBitmap, it must be lockable. CreateCursor failed");
delete[] pMonoMask;
delete[] pColorMask;
return NULL;
}
pSourceBitmap = (DWORD*)lock.pBits;
for (int j = (int)(Height - 1); j >= 0 ; j--)
{
for (UINT i = 0; i < Width; ++i)
{
DWORD pixel= pSourceBitmap[i*BitmapWidth/Width];
if (ISOPAQUE(pixel))
{
pColorMask[j*Width+i] = pixel;
}
else
{
pMonoMask[(j*Width+i)/8]
|= 1 << (7-((j*Width+i) % 8));
pColorMask[j*Width+i] = 0;
}
}
pSourceBitmap += lock.Pitch* BitmapHeight/4/Height;
}
if (FAILED(pCursorBitmap->UnlockRect()))
{
DPF_ERR("Driver surface failed to unlock pCursorBitmap");
}
/************************************************************************/
/* Initialize the bitmap header for the XOR data. */
/************************************************************************/
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = Width;
pbmi->bmiHeader.biHeight = Height;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = 32;
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage = Width*Height*sizeof(DWORD);
pbmi->bmiHeader.biXPelsPerMeter = 0;
pbmi->bmiHeader.biYPelsPerMeter = 0;
pbmi->bmiHeader.biClrUsed = 0;
pbmi->bmiHeader.biClrImportant = 0;
hwndDesktop = GetDesktopWindow();
hdcScreen = GetWindowDC(hwndDesktop);
if (0 == hdcScreen)
{
// Error getting the screen DC.
DPF_ERR("Failed to create screen DC");
delete[] pMonoMask;
delete[] pColorMask;
return NULL;
}
/********************************************************************/
/* Create XOR Bitmap */
/********************************************************************/
iconinfo.hbmColor = CreateDIBitmap(hdcScreen,
(LPBITMAPINFOHEADER)pbmi,
CBM_INIT,
pColorMask,
pbmi,
DIB_RGB_COLORS);
delete[] pColorMask;
/********************************************************************/
/* Release the DC. */
/********************************************************************/
ReleaseDC(hwndDesktop, hdcScreen);
if ( NULL == iconinfo.hbmColor)
{
delete[] pMonoMask;
return NULL;
}
/************************************************************************/
/* For the mono bitmap, use CreateCompatibleDC - this makes no */
/* difference on NT, but allows this code to work on Windows 95. */
/************************************************************************/
hdcMem = CreateCompatibleDC(NULL);
if ( NULL == hdcMem)
{
DPF_ERR("Failed to create DC");
delete[] pMonoMask;
DeleteObject( iconinfo.hbmColor );
return NULL;
}
/************************************************************************/
/* Create AND Mask (1bpp) - set the RGB colors to black and white. */
/************************************************************************/
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = Width;
pbmi->bmiHeader.biHeight = Height;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = 1;
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage = Width*Height/8;
pbmi->bmiHeader.biXPelsPerMeter = 0;
pbmi->bmiHeader.biYPelsPerMeter = 0;
pbmi->bmiHeader.biClrUsed = 2;
pbmi->bmiHeader.biClrImportant = 0;
pbmi->bmiColors[0].rgbRed = 0x00;
pbmi->bmiColors[0].rgbGreen = 0x00;
pbmi->bmiColors[0].rgbBlue = 0x00;
pbmi->bmiColors[0].rgbReserved = 0x00;
pbmi->bmiColors[1].rgbRed = 0xFF;
pbmi->bmiColors[1].rgbGreen = 0xFF;
pbmi->bmiColors[1].rgbBlue = 0xFF;
pbmi->bmiColors[1].rgbReserved = 0x00;
iconinfo.hbmMask = CreateDIBitmap(hdcMem,
(LPBITMAPINFOHEADER)pbmi,
CBM_INIT,
pMonoMask,
pbmi,
DIB_RGB_COLORS);
/************************************************************************/
/* Free the DC. */
/************************************************************************/
DeleteDC(hdcMem);
delete[] pMonoMask;
if ( NULL == iconinfo.hbmMask)
{
DPF_ERR("Failed to create AND mask");
DeleteObject( iconinfo.hbmColor );
return NULL;
}
hCursor = (HCURSOR) CreateIconIndirect(&iconinfo);
DeleteObject( iconinfo.hbmMask );
DeleteObject( iconinfo.hbmColor );
return hCursor;
}
HRESULT
CCursor::CursorInit(
UINT xHotSpot,
UINT yHotSpot,
CBaseSurface *pCursorBitmap)
{
HRESULT hr=S_OK;
D3DSURFACE_DESC desc;
HCURSOR oscursor;
ICONINFO cursorinfo;
BITMAP bmColor;
BITMAP bmMask;
HDC hdcBitmap;
HDC hdcCursorDdb;
ZeroMemory(&cursorinfo, sizeof cursorinfo);
m_dwCursorFlags &= ~DDRAWI_CURSORINIT;
if (NULL != pCursorBitmap)
{
hr = pCursorBitmap->GetDesc(&desc);
DXGASSERT(SUCCEEDED(hr));
if (desc.Format != D3DFMT_A8R8G8B8)
{
DPF_ERR("Invalid Format for pCursorBitmap. Must be D3DFMT_A8R8G8B8");
return D3DERR_INVALIDCALL;
}
if ((desc.Width -1) & desc.Width)
{
DPF_ERR("Failed to Initialize Cursor: Width must be a 2^n");
return D3DERR_INVALIDCALL;
}
if ((desc.Height -1) & desc.Height)
{
DPF_ERR("Failed to Initialize Cursor: Height must be a 2^n");
return D3DERR_INVALIDCALL;
}
if (desc.Width > m_pDevice->DisplayWidth())
{
DPF_ERR("Cursor Width must be smaller than DisplayWidth");
return D3DERR_INVALIDCALL;
}
if (desc.Height > m_pDevice->DisplayHeight())
{
DPF_ERR("Cursor Height must be smaller than DisplayHeight");
return D3DERR_INVALIDCALL;
}
if (desc.Width <= xHotSpot)
{
DPF_ERR("Cursor xHotSpot must be smaller than its Width");
return D3DERR_INVALIDCALL;
}
if (desc.Height <= yHotSpot)
{
DPF_ERR("Cursor yHotSpot must be smaller than its Height");
return D3DERR_INVALIDCALL;
}
}
else if ( NULL == m_hCursorDdb)
{
oscursor = SetCursor(NULL);
if (oscursor)
m_hOsCursor = oscursor;
else if (m_hOsCursor)
oscursor = m_hOsCursor;
desc.Width = GetSystemMetrics(SM_CXCURSOR);
desc.Height = GetSystemMetrics(SM_CYCURSOR); //default
if (oscursor && GetIconInfo(oscursor,&cursorinfo))
{
GetObject( cursorinfo.hbmMask, sizeof(BITMAP), &bmMask );
desc.Width = bmMask.bmWidth;
if (cursorinfo.hbmColor)
{
GetObject( cursorinfo.hbmColor, sizeof(BITMAP), &bmColor );
desc.Height = bmColor.bmHeight; //color cursor has only AND mask
}
else
{
desc.Height = bmMask.bmHeight/2;
}
}
}
else
return S_OK;
const D3D8_DRIVERCAPS* pDriverCaps=m_pDevice->GetCoreCaps();
if ((NULL != pCursorBitmap)
&& (
(
// either driver says it can support
(
(D3DCURSORCAPS_COLOR & pDriverCaps->D3DCaps.CursorCaps)
&&
(
(400 <= pDriverCaps->DisplayHeight)
||
(D3DCURSORCAPS_LOWRES & pDriverCaps->D3DCaps.CursorCaps)
)
)
&& ((UINT)GetSystemMetrics(SM_CXCURSOR) == desc.Width)
&& ((UINT)GetSystemMetrics(SM_CYCURSOR) == desc.Height)
)
// or windowed case where we have to use OS cursor
||
m_pDevice->SwapChain()->m_PresentationData.Windowed
// or there is no ddraw support
||
m_pDevice->Enum()->NoDDrawSupport(m_pDevice->AdapterIndex())
)
)
{
HCURSOR hCursor;
if (!m_pDevice->SwapChain()->m_PresentationData.Windowed
&& (NULL == m_hHWCursor))
{
SystemParametersInfo(SPI_GETMOUSETRAILS,0,&m_SavedMouseTrails,0);
if (m_SavedMouseTrails > 1)
{
// always make sure it's disabled
SystemParametersInfo(SPI_SETMOUSETRAILS,0,0,0);
}
}
hCursor = CreateColorCursor(xHotSpot,yHotSpot,
desc.Width, desc.Height, pCursorBitmap);
if ( NULL != hCursor)
{
if ( NULL != m_hHWCursor)
{
if ( GetCursor() == m_hHWCursor )
SetCursor(hCursor); // turn it on if it was on
if (!DestroyIcon((HICON)m_hHWCursor))
{
DPF_ERR("Failed to Destroy Old hwcursor Icon");
}
}
else
if ( DDRAWI_CURSORISON & m_dwCursorFlags)
{
SetCursor(hCursor); // turn it on if it was on
// make sure software cursor is off
m_dwCursorFlags &= ~DDRAWI_CURSORISON;
}
m_hHWCursor = hCursor;
m_dwCursorFlags |= DDRAWI_CURSORINIT;
return S_OK;
}
}
if (m_SavedMouseTrails > 1)
{
SystemParametersInfo(SPI_SETMOUSETRAILS,m_SavedMouseTrails,0,0);
m_SavedMouseTrails = 0;
}
SetCursor(NULL);
if ( NULL != m_hHWCursor )
{
if (!DestroyIcon((HICON)m_hHWCursor))
{
DPF_ERR("Failed to Destroy Old hwcursor Icon");
}
m_hHWCursor = NULL;
}
if (desc.Width != m_Width || desc.Height != m_Height)
{
DDSURFACEINFO SurfInfoArray[3];
D3D8_CREATESURFACEDATA CreateSurfaceData;
ZeroMemory(&CreateSurfaceData, sizeof(CreateSurfaceData));
Destroy();
ZeroMemory(SurfInfoArray, sizeof(SurfInfoArray));
for (int i = 0; i < 3; i++)
{
SurfInfoArray[i].cpWidth = desc.Width;
SurfInfoArray[i].cpHeight = desc.Height;
ZeroMemory(&CreateSurfaceData, sizeof(CreateSurfaceData));
CreateSurfaceData.hDD = m_pDevice->GetHandle();
CreateSurfaceData.pSList = &SurfInfoArray[i];
CreateSurfaceData.dwSCnt = 1;
CreateSurfaceData.Type = D3DRTYPE_SURFACE;
CreateSurfaceData.Pool = D3DPOOL_LOCALVIDMEM;
CreateSurfaceData.dwUsage = D3DUSAGE_OFFSCREENPLAIN;
CreateSurfaceData.Format = m_pDevice->DisplayFormat();
CreateSurfaceData.MultiSampleType = D3DMULTISAMPLE_NONE;
hr = m_pDevice->GetHalCallbacks()->CreateSurface(&CreateSurfaceData);
if (NULL == SurfInfoArray[i].hKernelHandle)
{
CreateSurfaceData.Pool = D3DPOOL_SYSTEMMEM;
hr = m_pDevice->GetHalCallbacks()->CreateSurface(&CreateSurfaceData);
}
DPF(10,"CursorInit CreateSurface returns hr=%08lx handle=%08lx",
hr, SurfInfoArray[i].hKernelHandle);
}
m_hCursorDdb = SurfInfoArray[0].hKernelHandle;
m_hFrontSave = SurfInfoArray[1].hKernelHandle;
m_hBackSave = SurfInfoArray[2].hKernelHandle;
if (m_hCursorDdb && m_hFrontSave && m_hBackSave)
{
m_Width = desc.Width;
m_Height = desc.Height;
}
else
{
DPF_ERR("Cursor not available for this device");
return D3DERR_NOTAVAILABLE;
}
}
if (NULL != pCursorBitmap)
{
D3D8_LOCKDATA lockData;
D3DLOCKED_RECT lock;
DWORD *pSourceBitmap;
INT SourcePitch;
ZeroMemory(&lockData, sizeof lockData);
hr = pCursorBitmap->LockRect(&lock, NULL, 0);
if (FAILED(hr))
{
DPF_ERR("Failed to lock pCursorBitmap surface; Surface must be lockable.");
return D3DERR_INVALIDCALL;
}
lockData.hDD = m_pDevice->GetHandle();
lockData.hSurface = m_hCursorDdb;
hr = m_pDevice->GetHalCallbacks()->Lock(&lockData);
if (FAILED(hr))
{
DPF_ERR("Failed to lock driver cursor surface.");
pCursorBitmap->UnlockRect();
return hr;
}
SourcePitch = lock.Pitch;
pSourceBitmap = (DWORD*)lock.pBits;
switch (m_pDevice->DisplayFormat())
{
case D3DFMT_A1R5G5B5:
{
BYTE *pScan = (BYTE *) lockData.lpSurfData;
for (UINT j = 0; j < m_Height; ++j)
{
WORD *pPixel = (WORD *) pScan;
for (UINT i = 0; i < m_Width; ++i)
{
if (ISOPAQUE(pSourceBitmap[i]))
{
*pPixel =
(WORD)FORMAT_8888_1555(pSourceBitmap[i]);
if (0 == (0x7FFF & *pPixel))
*pPixel |= 0x0421; //off black color
}
else
*pPixel = 0;
pPixel ++;
}
pScan += lockData.lPitch;
pSourceBitmap += SourcePitch/4;
}
}
break;
case D3DFMT_X1R5G5B5:
{
BYTE *pScan = (BYTE *) lockData.lpSurfData;
for (UINT j = 0; j < m_Height; ++j)
{
WORD *pPixel = (WORD *) pScan;
for (UINT i = 0; i < m_Width; ++i)
{
if (ISOPAQUE(pSourceBitmap[i]))
{
*pPixel =
(WORD)FORMAT_8888_555(pSourceBitmap[i]);
if (0 == *pPixel)
*pPixel |= 0x0421; //off black color
}
else
*pPixel = 0;
pPixel ++;
}
pScan += lockData.lPitch;
pSourceBitmap += SourcePitch/4;
}
}
break;
case D3DFMT_R5G6B5:
{
BYTE *pScan = (BYTE *) lockData.lpSurfData;
for (UINT j = 0; j < m_Height; ++j)
{
WORD *pPixel = (WORD *) pScan;
for (UINT i = 0; i < m_Width; ++i)
{
if (ISOPAQUE(pSourceBitmap[i]))
{
*pPixel =
(WORD)FORMAT_8888_565(pSourceBitmap[i]);
if (0 == *pPixel)
*pPixel |= 0x0821; //off black color
}
else
*pPixel = 0;
pPixel ++;
}
pScan += lockData.lPitch;
pSourceBitmap += SourcePitch/4;
}
}
break;
case D3DFMT_X8R8G8B8:
{
BYTE *pScan = (BYTE *) lockData.lpSurfData;
for (UINT j = 0; j < m_Height; ++j)
{
DWORD *pPixel = (DWORD *) pScan;
for (UINT i = 0; i < m_Width; ++i)
{
if (ISOPAQUE(pSourceBitmap[i]))
{
*pPixel = pSourceBitmap[i] & 0x00FFFFFF;
if (0 == *pPixel)
*pPixel |= 0x010101; //off black color
}
else
*pPixel = 0;
pPixel ++;
}
pScan += lockData.lPitch;
pSourceBitmap += SourcePitch/4;
}
}
break;
case D3DFMT_A8R8G8B8:
{
BYTE *pScan = (BYTE *) lockData.lpSurfData;
for (UINT j = 0; j < m_Height; ++j)
{
DWORD *pPixel = (DWORD *) pScan;
for (UINT i = 0; i < m_Width; ++i)
{
if (ISOPAQUE(pSourceBitmap[i]))
{
*pPixel = pSourceBitmap[i];
if (0 == (0x00FFFFFF & *pPixel))
*pPixel |= 0x010101; //off black color
}
else
*pPixel = 0;
pPixel ++;
}
pScan += lockData.lPitch;
pSourceBitmap += SourcePitch/4;
}
}
break;
default:
// this should never happen
DDASSERT(FALSE);
}
D3D8_UNLOCKDATA unlockData;
ZeroMemory(&unlockData, sizeof unlockData);
unlockData.hDD = m_pDevice->GetHandle();
unlockData.hSurface = m_hCursorDdb;
hr = m_pDevice->GetHalCallbacks()->Unlock(&unlockData);
if (FAILED(hr))
{
DPF_ERR("Driver surface failed to unlock driver cursor surface");
}
hr = pCursorBitmap->UnlockRect();
if (FAILED(hr))
{
DPF_ERR("Driver surface failed to unlock pCursorBitmap");
}
m_xCursorHotSpot = xHotSpot;
m_yCursorHotSpot = yHotSpot;
}
if (SUCCEEDED(hr))
m_dwCursorFlags |= DDRAWI_CURSORINIT;
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "SetVisibility"
BOOL
CCursor::SetVisibility(BOOL bVisible)
{
BOOL retval = FALSE;
if (DDRAWI_CURSORINIT & m_dwCursorFlags)
{
if (NULL == m_hHWCursor)
{
retval = (BOOL) (DDRAWI_CURSORISON & m_dwCursorFlags);
SetCursor(NULL);
if (bVisible)
{
if (!retval)
{
m_dwCursorFlags |= DDRAWI_CURSORISON;
Show(m_pDevice->SwapChain()->
PrimarySurface()->KernelHandle());
m_dwCursorFlags &= ~(DDRAWI_CURSORSAVERECT | DDRAWI_CURSORRECTSAVED);
}
}
else
{
Hide(m_pDevice->SwapChain()->
PrimarySurface()->KernelHandle());
m_dwCursorFlags &= ~(DDRAWI_CURSORISON |
DDRAWI_CURSORSAVERECT | DDRAWI_CURSORRECTSAVED);
}
}
else
{
if (m_hHWCursor == GetCursor())
{
if (!bVisible)
SetCursor(NULL);
retval = TRUE;
}
else
{
if (bVisible)
SetCursor(m_hHWCursor);
else
SetCursor(NULL);
}
}
}
return retval;
}
/*
* SetCursorProperties
*
* Setup a cursor
* This is the method visible to the outside world.
*/
#undef DPF_MODNAME
#define DPF_MODNAME "SetProperties"
HRESULT
CCursor::SetProperties(
UINT xHotSpot,
UINT yHotSpot,
CBaseSurface *pCursorBitmap)
{
HRESULT hr;
DPF(10,"ENTERAPI: SetCursorProperties "
"xh=%d yh=%d pCursorBitmap=%08lx",
xHotSpot,yHotSpot,pCursorBitmap);
m_dwCursorFlags &= ~(DDRAWI_CURSORSAVERECT | DDRAWI_CURSORRECTSAVED);
hr = Hide(m_pDevice->SwapChain()
->PrimarySurface()->KernelHandle());
if (FAILED(hr))
{
DPF_ERR("Failed to Hide Cursor.");
return hr;
}
hr = CursorInit(xHotSpot, yHotSpot, pCursorBitmap);
if (FAILED(hr))
{
DPF_ERR("Failed to CursorInit.");
return hr;
}
hr = Show(m_pDevice->SwapChain()->PrimarySurface()->KernelHandle());
return hr;
}
/*
* Cursor::SetPosition
*
* Setup a cursor
* This is the method visible to the outside world.
*/
#undef DPF_MODNAME
#define DPF_MODNAME "Cursor::SetPosition"
void
CCursor::SetPosition(
UINT xScreenSpace,
UINT yScreenSpace,
DWORD Flags)
{
HRESULT hr = S_OK;
if (DDRAWI_CURSORINIT & m_dwCursorFlags)
{
if ( m_hHWCursor)
{
if (xScreenSpace == m_xCursor && yScreenSpace == m_yCursor)
{
POINT current;
if (GetCursorPos(&current))
{
if ((current.x == (INT)xScreenSpace + m_MonitorOrigin.x) &&
(current.y == (INT)yScreenSpace + m_MonitorOrigin.y)
)
return;
}
}
else
{
m_xCursor = xScreenSpace;
m_yCursor = yScreenSpace;
}
SetCursorPos(xScreenSpace+m_MonitorOrigin.x,
yScreenSpace+m_MonitorOrigin.y);
return;
}
if (xScreenSpace == m_xCursor && yScreenSpace == m_yCursor)
return;
// only emulated fullscreen cursor ever gets down here
if (D3DCURSOR_IMMEDIATE_UPDATE & Flags)
hr = Hide(m_pDevice->SwapChain()->PrimarySurface()->KernelHandle());
else if (DDRAWI_CURSORISON & m_dwCursorFlags)
m_dwCursorFlags |= DDRAWI_CURSORSAVERECT;
m_xCursor = xScreenSpace;
m_yCursor = yScreenSpace;
if (m_xCursor >= m_pDevice->DisplayWidth())
{
m_xCursor = m_pDevice->DisplayWidth()-1;
}
if (m_yCursor >= m_pDevice->DisplayHeight())
{
m_yCursor = m_pDevice->DisplayHeight()-1;
}
if (D3DCURSOR_IMMEDIATE_UPDATE & Flags)
{
hr = Show(m_pDevice->SwapChain()->PrimarySurface()->KernelHandle());
}
}
else
{
m_xCursor = xScreenSpace;
m_yCursor = yScreenSpace;
}
return;
}