📄 ddrawoverlay.cpp
字号:
// DDraw.cpp: implementation of the CDDraw class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "apierr.h"
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define INITGUID
#include <objbase.h>
#include <initguid.h>
#include "Display.h"
#include <ddraw.h>
//#include "RECFILE.H"
//DLL_IMPORT CRecFile RecObj;
#pragma comment (lib,"ddraw.lib")
// Define some macros
#define INIT_DIRECTDRAW_STRUCT(x) (ZeroMemory(&x, sizeof(x)), x.dwSize=sizeof(x))
#define FULL_SCREEN_OVERLAY_UPDATE_HANDLE ((void *) 0x4)
#pragma data_seg(".shared")
int Dllcnt=0;
int Objcnt=0;
//LPDIRECTDRAW g_lpDD2=0;
LPDIRECTDRAWSURFACE3 g_lpDDSOverlay=0;
DWORD g_lpOverlayStartAddr=0;
int g_OverlayPitch=0;
int g_OverlayPixelDepth=0;
DWORD g_OverlayClearColor=OVERLAYCLRCOLOR;
DWORD g_OverlayDestColorKey=DESCOLORKEY;
int g_OverlayPixelID=-1;
DWORD g_ScreenH;
DWORD g_ScreenW;
BYTE * g_MaxOverlayStartAddr=0;
#pragma data_seg()
typedef struct {
HWND hWnd; //the window handle of this region belong to
int PixelId; //IF ID<0 mean I do not support this pixel
int PixelDepth; //BYTES
int Pitch;
//DWORD MStartAddress; //the region mem start linear address
//location relative to screen
RECT DRect; //in Screen Primary surface
RECT SRect; //in Overlay surface
int StartHeight; //the Region initialized height
int StartWidth; //the Region initialized width
}Region;
//struct DispRegion;
//Sub region state define
#define BVIDEO 1 //AVIDEO=0
#define PAGELOCK 2 //NODIRECTW=0
typedef struct {
void * pMDispRgn; //point main region ie DispRegion *
DWORD StartAddress; //the region mem start linear address
DWORD SrcBufAddress;//use for copy op
DWORD SrcBufH; //use for copy op number lines
DWORD SrcBufW_bytes; //use for copy op, one line bytes
DWORD SrcBufPitch; //use for copy op, one line wide bytes
DWORD SrcPitch; //only use for software write mode
RECT SrcRect; //in system memory (for Blt transfer)
RECT DesRect; //in Overlay or Screen Primary surface
RECT StartRect; //the sub region initialized RECT
LPDIRECTDRAWSURFACE3 pSrcSurf;
LPDIRECTDRAWSURFACE3 pDesSurf;
int HRatio; //use for fix sub region
int VRatio;
int State;
//HANDLE VidBufMutex;
PVOID VidBufLockVar;
} SubRegion;
typedef struct {
int RgnType; //the region type
union {
Region MRgn;
SubRegion SRgn;
} u;
} DispRegion;
typedef struct DispRegion_List {
DWORD ValidID; //ID=0x10540001; for check if is a valid region
struct DispRegion_List * pfront;
DispRegion * pDispNode;
struct DispRegion_List * pnext;
} DispRegionList;
//BYTE * g_MaxOverlayStartAddr=0;
int g_DispObjID=0;
extern unsigned int g_apierr;
//Disp Regon List Op
DispRegionList * pHeadList;
DispRegionList * pTailList;
int g_StartSearch=0;
int m_NodeCounter;
BOOL DeleteNode(DispRegion * prgn);
//return one hRgn
DispRegion * AllocNode();
//insert to tail
DispRegionList * InsertNode(DispRegion * prgn);
//remove in any location
BOOL RemoveNode(DispRegionList * pn);
void RemoveAllNode();
void StartSearchNode();
void StopSearchNode();
void * SearchOneNode(HANDLE hRgn);
BOOL ClearGDISurfaceRect(HWND hwnd, RECT * prect,COLORREF rgb);
HRESULT DDColorMatch(IDirectDrawSurface3 * pdds, COLORREF rgb);
BOOL ClearSurface( LPDIRECTDRAWSURFACE3 surf, RECT * rect,COLORREF rgb ,BOOL UseYUY2 );
BOOL FillYUY2OverlaySurface(LPDIRECTDRAWSURFACE3 surf,RECT * prect,COLORREF rgb);
BOOL FillSurface(LPDIRECTDRAWSURFACE3 surf,RECT * pdrect,DWORD Color,BOOL IsOverlay);
BOOL LockBuffer(PVOID * pLockVar, PVOID ownid,int waitms);
#define UnLockBuffer(pv) (* pv=0)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
static LPDIRECTDRAW g_lpDD2=0;
static LPDIRECTDRAWSURFACE3 g_lpDDSPrimary=0;
//static LPDIRECTDRAWSURFACE g_lpDDSPrimary=0;
static LPDIRECTDRAWCLIPPER g_lpDDClipper=0;
static DDCAPS * g_pDrvCaps=0;
static DDCAPS * g_pHELCaps=0;
static DWORD g_lpPrimaryStartAddr =0;
static DWORD g_PrimaryPitch=0;
static int g_PrimaryPixelDepth=0;
static BOOL g_MainDispRegionIsInstalled=FALSE;
//static int g_InitMode;
// These are the pixel formats this app supports. Most display adapters
// with overlay support will recognize one or more of these formats.
// The first on our list is the 16-bit RGB formats. These have the widest
// support.
static DDPIXELFORMAT g_ddpfOverlayFormats[] =
{ {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x7C00, 0x03e0, 0x001F, 0}, // 0: 16-bit RGB 5:5:5 (#define RGB555DD 0)
{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0xF800, 0x07e0, 0x001F, 0}, // 1: 16-bit RGB 5:6:5 (#define RGB565DD 1)
{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 24, 0xFF0000, 0xFF00, 0x00FF, 0}, // 2: 24-bit RGB 8:8:8 (#define RGB888DD 2)
{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 32, 0xFF0000, 0xFF00, 0x00FF, 0}, // 2: 24-bit RGB 8:8:8 (#define RGB888DD 2)
// {sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('U','Y','V','Y'),0,0,0,0,0}, // UYVY
{sizeof(DDPIXELFORMAT), DDPF_FOURCC,0x32595559,0,0,0,0,0} //3: 16 bit YUY2 (#define YUY2_FOURCCDD 3)
};
//CreateSurface Mode define
#define SYSMEMSURF 0
#define VIDMEMSURF 1
//err=2
CDDrawOverlay::CDDrawOverlay(int Mode)
{
int pixid;
m_PrimaryPixelID=-1;
m_OK=FALSE;
m_NodeCounter=0;
m_Err.errloc=0;
m_Err.err=0;
m_FirstObj=FALSE;
g_DispObjID=Dllcnt;
//g_InitMode=Mode;
try {
pHeadList=NULL;
pTailList=NULL;
m_Err.err=InitDDraw();
m_Err.errloc=FN_InitDDraw_LOC;
if (m_Err.err) {throw apierr(DDRAW_BASEERR,"call InitDDraw err",TRUE);};
if (!GetCaps()) {throw apierr(DDRAW_BASEERR+1,"call GetCaps err",TRUE);};
if (!CreatePrimary()) {throw apierr(DDRAW_BASEERR+2,"call CreatePrimary err",TRUE);};
if (!GetScreenDispParams()) {throw apierr(DDRAW_BASEERR+3,"call GetScreenDispParams err",TRUE);};
pixid=GetRGBPixelID(-1);
if (pixid<0)
{
::MessageBox(0,"The Current Display Mode do not support my pixel Format!","Error",MB_OK);
DestoryPrimary();
return ; //return 0
}
m_PrimaryPixelID=pixid;
//if only create ddraw primary then return
if (!(Mode&SUPPORT_OVERLAY_WIN))
{
m_OK=TRUE;
Objcnt++;
return;
};
//if this is not the first obj then return true (do not need create overlay)
if (Objcnt>0)
{
Objcnt++;
m_OK=TRUE;
return;
}
m_FirstObj=TRUE;
//it is not first overlay object
//need overlay
if (!IsSupportOverlay())
{ //if do not support overlay only use primary
//DestoryPrimary();
g_OverlayPixelID=-1;
g_lpDDSOverlay=0;
g_lpOverlayStartAddr=0;
g_OverlayPitch=0;
g_OverlayPixelDepth=0;
g_MaxOverlayStartAddr=0;
return ; //return false
};
if ((Mode&(SUPPORT_OVERLAYFULL_WIN|SUPPORT_VID_B))==(SUPPORT_OVERLAYFULL_WIN|SUPPORT_VID_B))
{
if((pixid=CreateOverlay(g_ScreenW,g_ScreenH,YUY2_FOURCCDD))<0)
{throw apierr(DDRAW_BASEERR+16,"call CreateOverlay err",TRUE);};
ClearSurface(g_lpDDSOverlay, NULL,g_OverlayClearColor,TRUE);
}
else if ((Mode&(SUPPORT_OVERLAYFULL_WIN))==SUPPORT_OVERLAYFULL_WIN)
{
if((pixid=CreateOverlay(g_ScreenW,g_ScreenH,-1))<0)
{throw apierr(DDRAW_BASEERR+17,"call CreateOverlay err",TRUE);};
ClearSurface(g_lpDDSOverlay, NULL,g_OverlayClearColor,FALSE);
}
else
{
m_Err.err=NOT_SUPPORT_ERR;
m_Err.errloc=CHECK_PARAMS_LOC;
return;
}
if (!DisplayOverlay(FULL_SCREEN_OVERLAY_UPDATE_HANDLE))
{throw apierr(DDRAW_BASEERR+18,"UpdateOverlay err",TRUE);};
Objcnt++;
g_OverlayPixelID=pixid;
m_OK=TRUE;
}
catch(...)
{
//the error I do not expect
if (!g_apierr)
{throw apierr(DDRAW_BASEERR+EXCETPERROR,"except err in CDDraw::CDDraw()",TRUE);};
}
}
CDDrawOverlay::~CDDrawOverlay()
{
if (m_OK)
{
try {
DestoryAllRegions();
DestoryDDraw();
}
catch (...)
{
throw apierr(DDRAW_BASEERR+EXCETPERROR,"except err in CDDraw::~CDDraw()",TRUE);
}
m_OK=FALSE;
}
}
BOOL CDDrawOverlay::IsTheClassOK()
{
return m_OK;
}
BOOL CDDrawOverlay::GetErrCode(ErrDispCode * pErr)
{
if (pErr)
{
* pErr=m_Err;
//clear err
m_Err.err=0;
m_Err.errloc=0;
return TRUE;
}
else
return FALSE;
}
HRESULT CDDrawOverlay::InitDDraw()
{
HRESULT ddrval;
LPDIRECTDRAW lpDDraw1;
// LPDIRECTDRAWSURFACE lpDDSPrimary;
// DDSURFACEDESC desc;
// lpDDSPrimary=0;
lpDDraw1=0;
// m_Ok=FALSE;
ddrval = DirectDrawCreate(NULL, &lpDDraw1, NULL);
if (ddrval != DD_OK) return ddrval;
ddrval=lpDDraw1->QueryInterface(IID_IDirectDraw2,(void**)&g_lpDD2);
lpDDraw1->Release();
if (ddrval!=S_OK) return ddrval;
ddrval=g_lpDD2->SetCooperativeLevel( 0, DDSCL_NORMAL);
return ddrval;
}
void CDDrawOverlay::DestoryDDraw()
{
// DestoryPrimary();
if (Objcnt==1)
{
DestoryOverlay();
Objcnt=0;
}
else
{
Objcnt--;
if (Objcnt<0)
Objcnt=0;
};
DestoryPrimary();
if (g_lpDD2)
{
g_lpDD2->Release();
g_lpDD2=0;
}
}
BOOL CDDrawOverlay::GetCaps()
{
DDCAPS DrvCaps,HELCaps;
HRESULT ddrval;
ZeroMemory( &DrvCaps, sizeof(DDCAPS) );
ZeroMemory( &HELCaps, sizeof(DDCAPS) );
DrvCaps.dwSize = sizeof(DrvCaps); //make sure DD knows size
HELCaps.dwSize = sizeof(HELCaps); //make sure DD knows size
ddrval=g_lpDD2->GetCaps(&DrvCaps,&HELCaps);
m_Err.err=ddrval;
m_Err.errloc=DD_GetCaps_LOC;
if (ddrval!=DD_OK) return FALSE;
g_pDrvCaps=&DrvCaps;
g_pHELCaps=&HELCaps;
OutPutCaps();
g_pDrvCaps=0;
g_pHELCaps=0;
return TRUE;
}
BOOL CDDrawOverlay::GetCaps(MyCaps * pMyHWCaps,MyCaps * pMyHELCaps)
{
BOOL ret=FALSE;
try {
if (!m_OK) return FALSE;
memcpy (pMyHWCaps,&m_MyHWCaps,sizeof(m_MyHWCaps));
memcpy (pMyHELCaps,&m_MyHELCaps,sizeof(m_MyHELCaps));
ret=TRUE;
}
catch(...)
{
throw apierr(DDRAW_BASEERR+EXCETPERROR,"except err in CDDraw::GetCaps",TRUE);
}
return ret;
}
void CDDrawOverlay::OutPutCaps()
{
ZeroMemory( &m_MyHWCaps, sizeof(m_MyHWCaps) );
if (g_pDrvCaps)
{
m_MyHWCaps.Blt=g_pDrvCaps->dwCaps&DDCAPS_BLT;
m_MyHWCaps.BltStetch=g_pDrvCaps->dwCaps&DDCAPS_BLTSTRETCH;
m_MyHWCaps.BltSys=g_pDrvCaps->dwCaps&DDCAPS_CANBLTSYSMEM;
//pMyHWCaps->BltQueue=g_pDrvCaps->dwCaps&DDCAPS_BLTQUEUE;
m_MyHWCaps.BltFOURCC=g_pDrvCaps->dwCaps&DDCAPS_BLTFOURCC;
m_MyHWCaps.Overlay=g_pDrvCaps->dwCaps&DDCAPS_OVERLAY;
m_MyHWCaps.OverlayFOURCC=g_pDrvCaps->dwCaps&DDCAPS_OVERLAYFOURCC;
m_MyHWCaps.OverlayStretch=g_pDrvCaps->dwCaps&DDCAPS_OVERLAYSTRETCH;
m_MyHWCaps.OverlayDesColorKey=g_pDrvCaps->dwCKeyCaps & DDCKEYCAPS_DESTOVERLAY;
m_MyHWCaps.OverlaySrcColorKey=g_pDrvCaps->dwCKeyCaps & DDCKEYCAPS_SRCOVERLAY;
//m_MyHWCaps.OverlayClip=g_pDrvCaps->dwCaps&DDCAPS_OVERLAYCANTCLIP;
// m_MyHWCaps.AutoFlipOverlay=g_pDrvCaps.;
m_MyHWCaps.dwNumFourCCCodes=g_pDrvCaps->dwNumFourCCCodes;
// minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
m_MyHWCaps.dwMinOverlayStretch=g_pDrvCaps->dwMinOverlayStretch;
// maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
m_MyHWCaps.dwMaxOverlayStretch=g_pDrvCaps->dwMaxOverlayStretch;
// maximum number of visible overlays
m_MyHWCaps.dwMaxVisibleOverlays=g_pDrvCaps->dwMaxVisibleOverlays;
// current number of visible overlays
m_MyHWCaps.dwCurrVisibleOverlays=g_pDrvCaps->dwCurrVisibleOverlays;
//BLT Caps
//system to video
m_MyHWCaps.SysToVidBlt=g_pDrvCaps->dwSVBCaps;
//video to system
m_MyHWCaps.VidToSysBlt=g_pDrvCaps->dwVSBCaps;
m_MyHWCaps.dwAlignBoundarySrc=g_pDrvCaps->dwAlignBoundarySrc;
m_MyHWCaps.dwAlignSizeSrc=g_pDrvCaps->dwAlignSizeSrc;
m_MyHWCaps.dwAlignBoundaryDest=g_pDrvCaps->dwAlignBoundaryDest;
m_MyHWCaps.dwAlignSizeDest=g_pDrvCaps->dwAlignSizeDest;
}
ZeroMemory( &m_MyHELCaps, sizeof(m_MyHELCaps) );
if (g_pHELCaps)
{
m_MyHELCaps.Blt=g_pHELCaps->dwCaps&DDCAPS_BLT;
m_MyHELCaps.BltStetch=g_pHELCaps->dwCaps&DDCAPS_BLTSTRETCH;
m_MyHELCaps.BltSys=g_pHELCaps->dwCaps&DDCAPS_CANBLTSYSMEM;
//m_MyHWCaps.BltQueue=g_pDrvCaps.dwCaps&DDCAPS_BLTQUEUE;
m_MyHELCaps.Overlay=g_pHELCaps->dwCaps&DDCAPS_OVERLAY;
m_MyHELCaps.OverlayFOURCC=g_pHELCaps->dwCaps&DDCAPS_OVERLAYFOURCC;
m_MyHELCaps.BltFOURCC=g_pHELCaps->dwCaps&DDCAPS_BLTFOURCC;
m_MyHELCaps.OverlayStretch=g_pHELCaps->dwCaps&DDCAPS_OVERLAYSTRETCH;
//pMyHELCaps.OverlayClip=g_pHELCaps->dwCaps&DDCAPS_OVERLAYCANTCLIP;
// pMyHELCaps.AutoFlipOverlay=g_DrvCaps.;
// minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
m_MyHELCaps.dwMinOverlayStretch=g_pHELCaps->dwMinOverlayStretch;
// maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3
m_MyHELCaps.dwMaxOverlayStretch=g_pHELCaps->dwMaxOverlayStretch;
// maximum number of visible overlays
m_MyHELCaps.dwMaxVisibleOverlays=g_pHELCaps->dwMaxVisibleOverlays;
// current number of visible overlays
m_MyHELCaps.dwCurrVisibleOverlays=g_pHELCaps->dwCurrVisibleOverlays;
//BLT Caps
//system to video
m_MyHELCaps.SysToVidBlt=g_pHELCaps->dwSVBCaps;
//video to system
m_MyHELCaps.VidToSysBlt=g_pHELCaps->dwVSBCaps;
}
}
//the Primary and Backbuff Surf is FULL screen
BOOL CDDrawOverlay::CreatePrimary(BOOL IsSupportFlip)
{
HRESULT ddrval;
DDSURFACEDESC ddsd; // A surface description structure
DDSURFACEDESC DDSDesc;
// Create the primary surface. The primary surface is the full screen -
// since we're a windowed app - we'll just write to the portion of the
// screen within our window.
INIT_DIRECTDRAW_STRUCT(ddsd);
//memset(&ddsd, 0, sizeof(ddsd)); // Set all fields of struct to 0 and set .dwSize to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -