2006-07-16 17:13 |
多谢,我还是好好看看DSound的东西吧。
至于我的封装,在错误报告部分我只是加上了MessageBox,方便我知道哪里有问题,如果上传到VCKBase上感觉有点丢人;不过自己感觉那些汇编代码写得还不错,所以发到这里,大家帮我参谋参谋,如有不是希望大家指出来。
//下面是代码(仅cpp,头文件只有类的定义,没必要贴出来)
#pragma comment(lib,"dxguid.lib")
#pragma comment(lib,"ddraw.lib")
#include <fstream>
using namespace std;
#include <olectl.h>
#include "GKLDirectDraw.h"
GKLDirectDraw::GKLDirectDraw(bool iswindow, DWORD width, DWORD height, DWORD bpp)
: ISWINDOW(iswindow)
, WIDTH(width)
, HEIGHT(height)
, BPP(bpp)
, mpDD7(NULL)
, mpDDSF(NULL)
, mpDDSB(NULL)
, mpDDC(NULL)
, mleft(0)
, mtop(0)
{
}
GKLDirectDraw::~GKLDirectDraw(void)
{
release();
}
bool GKLDirectDraw::ddrawinit(HWND hwnd)
{
DDSURFACEDESC2 ddsd2;
HRESULT ddrval;
if(mpDD7!=NULL)
{
MessageBox(NULL,"Error in GKLDirectDraw::ddrawinit","Error",MB_OK);
return false;
}
ddrval=DirectDrawCreateEx(NULL,(void**)&mpDD7,IID_IDirectDraw7,NULL);
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::ddrawinit","Error",MB_OK);
return false;
}
if(ISWINDOW)
{
ddrval=mpDD7->SetCooperativeLevel(hwnd,DDSCL_NORMAL);
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::ddrawinit","Error",MB_OK);
return false;
}
memset(&ddsd2,0,sizeof(ddsd2));
ddsd2.dwSize=sizeof(ddsd2);
ddsd2.dwFlags=DDSD_CAPS;
ddsd2.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE;
ddrval=mpDD7->CreateSurface(&ddsd2,&mpDDSF,NULL);
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::ddrawinit","Error",MB_OK);
return false;
}
ddrval=mpDD7->CreateClipper(NULL,&mpDDC,NULL);
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::ddrawinit","Error",MB_OK);
return false;
}
ddrval=mpDDC->SetHWnd(NULL,hwnd);
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::ddrawinit","Error",MB_OK);
return false;
}
ddrval=mpDDSF->SetClipper(mpDDC);
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::ddrawinit","Error",MB_OK);
return false;
}
}
else
{
ddrval=mpDD7->SetCooperativeLevel(hwnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN);
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::ddrawinit","Error",MB_OK);
return false;
}
do
{
ddrval=mpDD7->SetDisplayMode(WIDTH,HEIGHT,BPP,0,0);
}while(ddrval==DDERR_NOEXCLUSIVEMODE);
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::ddrawinit","Error",MB_OK);
return false;
}
memset(&ddsd2,0,sizeof(ddsd2));
ddsd2.dwSize=sizeof(ddsd2);
ddsd2.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
ddsd2.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX;
ddsd2.dwBackBufferCount=1;
ddrval=mpDD7->CreateSurface(&ddsd2,&mpDDSF,NULL);
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::ddrawinit","Error",MB_OK);
return false;
}
memset(&ddsd2,0,sizeof(ddsd2));
ddsd2.dwSize=sizeof(ddsd2);
ddsd2.dwFlags=DDSD_CAPS;
ddsd2.ddsCaps.dwCaps=DDSCAPS_BACKBUFFER;
ddrval=mpDDSF->GetAttachedSurface(&ddsd2.ddsCaps,&mpDDSBB);
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::ddrawinit","Error",MB_OK);
return false;
}
}
memset(&ddsd2,0,sizeof(ddsd2));
ddsd2.dwSize=sizeof(ddsd2);
ddsd2.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
ddsd2.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
ddsd2.dwWidth=WIDTH;
ddsd2.dwHeight=HEIGHT;
ddrval=mpDD7->CreateSurface(&ddsd2,&mpDDSB,NULL);
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::ddrawinit","Error",MB_OK);
return false;
}
return true;
}
bool GKLDirectDraw::loadpicture(LPDIRECTDRAWSURFACE7 &pDDS, const char *filename)
{
IStream *pstm;
IPicture *ppic;
ifstream fin;
HRESULT hr,ddrval;
if(mpDD7==NULL)
{
MessageBox(NULL,"Error in GKLDirectDraw::loadpicture","Error",MB_OK);
return false;
}
//Open the file
fin.open(filename,ios::binary);
if(fin==NULL)
{
MessageBox(NULL,"Error in GKLDirectDraw::loadpicture","Error",MB_OK);
return false;
}
fin.seekg(0,ios::end);
DWORD fsize=fin.tellg();
fin.seekg(0);
//Read data
HGLOBAL hglobal=GlobalAlloc(GMEM_MOVEABLE,fsize);
char *pbuf=(char*)GlobalLock(hglobal);
if(pbuf==NULL)
{
MessageBox(NULL,"Error in GKLDirectDraw::loadpicture","Error",MB_OK);
return false;
}
fin.read(pbuf,fsize);
GlobalUnlock(hglobal);
hr=CreateStreamOnHGlobal(hglobal,true,&pstm);
if(hr!=0)
{
MessageBox(NULL,"Error in GKLDirectDraw::loadpicture","Error",MB_OK);
return false;
}
hr=OleLoadPicture(pstm,0,true,IID_IPicture,(void**)&ppic);
if(hr!=0)
{
MessageBox(NULL,"Error in GKLDirectDraw::loadpicture","Error",MB_OK);
return false;
}
pstm->Release();
//Get parameters
long hmwidth=0,hmheight=0;
ppic->get_Width(&hmwidth);
ppic->get_Height(&hmheight);
DWORD width=0,height=0;
HDC hdc;
hr=mpDDSB->GetDC(&hdc);
if(hr!=0)
{
MessageBox(NULL,"Error in GKLDirectDraw::loadpicture","Error",MB_OK);
return false;
}
width=MulDiv(hmwidth,GetDeviceCaps(hdc,LOGPIXELSX),2540);
height=MulDiv(hmheight,GetDeviceCaps(hdc,LOGPIXELSX),2540);
mpDDSB->ReleaseDC(hdc);
//CreateSurface
DDSURFACEDESC2 ddsd2;
memset(&ddsd2,0,sizeof(ddsd2));
ddsd2.dwSize=sizeof(ddsd2);
ddsd2.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
ddsd2.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
ddsd2.dwWidth=width;
ddsd2.dwHeight=height;
ddrval=mpDD7->CreateSurface(&ddsd2,&pDDS,NULL);
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::loadpicture","Error",MB_OK);
return false;
}
//Render
hr=pDDS->GetDC(&hdc);
if(hr!=0)
{
MessageBox(NULL,"Error in GKLDirectDraw::loadpicture","Error",MB_OK);
return false;
}
hr=ppic->Render(hdc,0,0,width,height,0,hmheight,hmwidth,-hmheight,NULL);
if(hr!=0)
{
MessageBox(NULL,"Error in GKLDirectDraw::loadpicture","Error",MB_OK);
return false;
}
pDDS->ReleaseDC(hdc);
ppic->Release();
return true;
}
bool GKLDirectDraw::flip(void)
{
HRESULT ddrval;
if(mpDD7==NULL)
{
MessageBox(NULL,"Error in GKLDirectDraw::flip","Error",MB_OK);
return false;
}
if(ISWINDOW)
{
RECT rect={mleft,mtop,mleft+WIDTH,mtop+HEIGHT};
ddrval=mpDDSF->Blt(&rect,mpDDSB,NULL,DDBLT_WAIT,NULL);
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::flip","Error",MB_OK);
return false;
}
}
else
{
ddrval=mpDDSBB->BltFast(0,0,mpDDSB,NULL,DDBLTFAST_WAIT);
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::flip","Error",MB_OK);
return false;
}
do
{
ddrval=mpDDSF->Flip(NULL,0);
if(ddrval==DDERR_SURFACELOST)
{
ddrval=mpDD7->RestoreAllSurfaces();
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::flip","Error",MB_OK);
return false;
}
ddrval=mpDDSF->Flip(NULL,0);
}
}while(ddrval==DDERR_WASSTILLDRAWING);
if(ddrval!=DD_OK)
{
MessageBox(NULL,"Error in GKLDirectDraw::flip","Error",MB_OK);
return false;
}
}
return true;
}
void GKLDirectDraw::release(void)
{
if(mpDD7!=NULL)
{
if(mpDDC!=NULL)
{
mpDDC->Release();
mpDDC=NULL;
}
if(mpDDSB!=NULL)
{
mpDDSB->Release();
mpDDSB=NULL;
}
if(mpDDSF!=NULL)
{
mpDDSF->Release();
mpDDSF=NULL;
}
mpDD7->Release();
mpDD7=NULL;
}
}
bool GKLDirectDraw::AdaptParam(int &xSrc, int &ySrc, int &xDest, int &yDest, int &Width, int &Height, DWORD SrcWidth, DWORD SrcHeight, DWORD DestWidth, DWORD DestHeight)
{
if(xSrc<0){xDest-=xSrc;Width+=xSrc;xSrc=0;}
if(ySrc<0){yDest-=ySrc;Height+=ySrc;ySrc=0;}
if(xDest<0){xSrc-=xDest;Width+=xDest;xDest=0;}
if(yDest<0){ySrc-=yDest;Height+=yDest;yDest=0;}
if(xSrc+Width>(int)SrcWidth)Width=(int)SrcWidth-xSrc;
if(ySrc+Height>(int)SrcHeight)Height=(int)SrcHeight-ySrc;
if(xDest+Width>(int)DestWidth)Width=(int)DestWidth-xDest;
if(yDest+Height>(int)DestHeight)Height=(int)DestHeight-yDest;
return (Width>0)&&(Height>0);
}
bool GKLDirectDraw::AdaptParam(int &x, int &y, int &Width, int &Height, DWORD maxWidth, DWORD maxHeight)
{
if(x<0){Width+=x;x=0;}
if(y<0){Height+=y;y=0;}
if(x+Width>(int)maxWidth)Width=(int)maxWidth-x;
if(y+Height>(int)maxHeight)Height=(int)maxHeight-y;
return (Width>0)&&(Height>0);
}
void GKLDirectDraw::Alpha32(LPDIRECTDRAWSURFACE7 pSrc, LPDIRECTDRAWSURFACE7 pDest, int xSrc, int ySrc, int xDest, int yDest, int Width, int Height, int alpha)
{
DDSURFACEDESC2 ddsdSrc,ddsdDest;
ddsdSrc.dwSize=sizeof(ddsdSrc);
ddsdDest.dwSize=sizeof(ddsdDest);
pSrc->Lock(NULL,&ddsdSrc,DDLOCK_WAIT,NULL);
pDest->Lock(NULL,&ddsdDest,DDLOCK_WAIT,NULL);
if(!AdaptParam(xSrc,ySrc,xDest,yDest,Width,Height,ddsdSrc.dwWidth,ddsdSrc.dwHeight,ddsdDest.dwWidth,ddsdDest.dwHeight))return;
char *startSrc=(char*)ddsdSrc.lpSurface;
char *startDest=(char*)ddsdDest.lpSurface;
startSrc+=(ySrc*ddsdSrc.lPitch+(xSrc<<2));
startDest+=(yDest*ddsdDest.lPitch+(xDest<<2));
__asm
{
pxor mm0,mm0;
movd mm7,alpha;
punpcklwd mm7,mm7;
punpckldq mm7,mm7;
}
for(int ty=0;ty<Height;ty++)
{
__asm
{
xor ecx,ecx;
mov eax,startSrc;
mov ebx,startDest;
mov edx,Width;
AGAIN:
cmp dword ptr [eax],0;
je NEXT;
movd mm1,dword ptr [eax];
movd mm2,dword ptr [ebx];
punpcklbw mm1,mm0;
punpcklbw mm2,mm0;
movq mm3,mm1;
psubw mm3,mm2;
pmullw mm3,mm7;
psrlw mm3,8;
paddb mm2,mm3;
packuswb mm2,mm0;
movd dword ptr [ebx],mm2;
NEXT:
add eax,4;
add ebx,4;
inc ecx;
cmp ecx,edx;
jb AGAIN;
}
startSrc+=ddsdSrc.lPitch;
startDest+=ddsdDest.lPitch;
}
__asm
{
emms;
}
pDest->Unlock(NULL);
pSrc->Unlock(NULL);
}
void GKLDirectDraw::Add32(LPDIRECTDRAWSURFACE7 pSrc, LPDIRECTDRAWSURFACE7 pDest, int xSrc, int ySrc, int xDest, int yDest, int Width, int Height)
{
DDSURFACEDESC2 ddsdSrc,ddsdDest;
ddsdSrc.dwSize=sizeof(ddsdSrc);
ddsdDest.dwSize=sizeof(ddsdDest);
pSrc->Lock(NULL,&ddsdSrc,DDLOCK_WAIT,NULL);
pDest->Lock(NULL,&ddsdDest,DDLOCK_WAIT,NULL);
if(!AdaptParam(xSrc,ySrc,xDest,yDest,Width,Height,ddsdSrc.dwWidth,ddsdSrc.dwHeight,ddsdDest.dwWidth,ddsdDest.dwHeight))return;
char *startSrc=(char*)ddsdSrc.lpSurface;
char *startDest=(char*)ddsdDest.lpSurface;
startSrc+=(ySrc*ddsdSrc.lPitch+(xSrc<<2));
startDest+=(yDest*ddsdDest.lPitch+(xDest<<2));
for(int ty=0;ty<Height;ty++)
{
__asm
{
xor ecx,ecx;
mov eax,startSrc;
mov ebx,startDest;
mov edx,Width;
AGAIN:
movd mm1,dword ptr [eax];
movd mm2,dword ptr [ebx];
paddusb mm2,mm1;
movd dword ptr [ebx],mm2;
NEXT:
add eax,4;
add ebx,4;
inc ecx;
cmp ecx,edx;
jb AGAIN;
}
startSrc+=ddsdSrc.lPitch;
startDest+=ddsdDest.lPitch;
}
__asm
{
emms;
}
pDest->Unlock(NULL);
pSrc->Unlock(NULL);
}
void GKLDirectDraw::Sub32(LPDIRECTDRAWSURFACE7 pSrc, LPDIRECTDRAWSURFACE7 pDest, int xSrc, int ySrc, int xDest, int yDest, int Width, int Height)
{
DDSURFACEDESC2 ddsdSrc,ddsdDest;
ddsdSrc.dwSize=sizeof(ddsdSrc);
ddsdDest.dwSize=sizeof(ddsdDest);
pSrc->Lock(NULL,&ddsdSrc,DDLOCK_WAIT,NULL);
pDest->Lock(NULL,&ddsdDest,DDLOCK_WAIT,NULL);
if(!AdaptParam(xSrc,ySrc,xDest,yDest,Width,Height,ddsdSrc.dwWidth,ddsdSrc.dwHeight,ddsdDest.dwWidth,ddsdDest.dwHeight))return;
char *startSrc=(char*)ddsdSrc.lpSurface;
char *startDest=(char*)ddsdDest.lpSurface;
startSrc+=(ySrc*ddsdSrc.lPitch+(xSrc<<2));
startDest+=(yDest*ddsdDest.lPitch+(xDest<<2));
for(int ty=0;ty<Height;ty++)
{
__asm
{
xor ecx,ecx;
mov eax,startSrc;
mov ebx,startDest;
mov edx,Width;
AGAIN:
movd mm1,dword ptr [eax];
movd mm2,dword ptr [ebx];
psubusb mm2,mm1;
movd dword ptr [ebx],mm2;
NEXT:
add eax,4;
add ebx,4;
inc ecx;
cmp ecx,edx;
jb AGAIN;
}
startSrc+=ddsdSrc.lPitch;
startDest+=ddsdDest.lPitch;
}
__asm
{
emms;
}
pDest->Unlock(NULL);
pSrc->Unlock(NULL);
}
void GKLDirectDraw::Dec32(LPDIRECTDRAWSURFACE7 p, int x, int y, int Width, int Height, int dec)
{
DDSURFACEDESC2 ddsd;
ddsd.dwSize=sizeof(ddsd);
p->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);
if(!AdaptParam(x,y,Width,Height,ddsd.dwWidth,ddsd.dwHeight))return;
char *start=(char*)ddsd.lpSurface;
start+=(y*ddsd.lPitch+(x<<2));
__asm
{
pxor mm0,mm0;
movd mm7,dec;
punpcklwd mm7,mm7;
punpckldq mm7,mm7;
}
for(int ty=0;ty<Height;ty++)
{
__asm
{
xor ecx,ecx;
mov eax,start;
mov edx,Width;
AGAIN:
movd mm1,dword ptr [eax];
punpcklbw mm1,mm0;
pmullw mm1,mm7;
psrlw mm1,8;
packuswb mm1,mm0;
movd dword ptr [eax],mm1;
NEXT:
add eax,4;
inc ecx;
cmp ecx,edx;
jb AGAIN;
}
start+=ddsd.lPitch;
}
__asm
{
emms;
}
p->Unlock(NULL);
}
void GKLDirectDraw::Blur32(LPDIRECTDRAWSURFACE7 p, int x, int y, int Width, int Height)
{
DDSURFACEDESC2 ddsd;
ddsd.dwSize=sizeof(ddsd);
p->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);
if(!AdaptParam(x,y,Width,Height,ddsd.dwWidth,ddsd.dwHeight))return;
x++;y++;Width-=2;Height-=2;
char *start=(char*)ddsd.lpSurface,*up,*down;
start+=(y*ddsd.lPitch+(x<<2));
up=start-ddsd.lPitch;
down=start+ddsd.lPitch;
__asm
{
pxor mm0,mm0;
}
for(int ty=0;ty<Height;ty++)
{
__asm
{
xor ecx,ecx;
mov eax,start;
mov edx,Width;
mov esi,up;
mov edi,down;
movd mm1,dword ptr [eax-4];
punpcklbw mm1,mm0;
AGAIN:
movd mm2,dword ptr [eax+4];
movd mm3,dword ptr [esi];
movd mm4,dword ptr [edi];
punpcklbw mm2,mm0;
punpcklbw mm3,mm0;
punpcklbw mm4,mm0;
paddw mm2,mm1;
paddw mm2,mm3;
paddw mm2,mm4;
psrlw mm2,2;
movq mm1,mm2;
packuswb mm2,mm0;
movd dword ptr [eax],mm2;
NEXT:
add eax,4;
add esi,4;
add edi,4;
inc ecx;
cmp ecx,edx;
jb AGAIN;
}
start+=ddsd.lPitch;
up+=ddsd.lPitch;
down+=ddsd.lPitch;
}
__asm
{
emms;
}
p->Unlock(NULL);
}
void GKLDirectDraw::resetlefttop(void)
{
if(!ISWINDOW)
return;
if(mpDDC!=NULL)
{
HWND hwnd;
mpDDC->GetHWnd(&hwnd);
if(IsWindow(hwnd))
{
RECT wrect,crect;
GetWindowRect(hwnd,&wrect);
GetClientRect(hwnd,&crect);
MoveWindow(hwnd,wrect.left,wrect.top
,WIDTH+wrect.right+crect.left-wrect.left-crect.right
,HEIGHT+wrect.bottom+crect.top-wrect.top-crect.bottom
,true);
POINT point={0,0};
ClientToScreen(hwnd,&point);
mleft=point.x;
mtop=point.y;
}
}
}
void GKLDirectDraw::getlefttop(const DWORD *pleft, const DWORD *ptop)
{
pleft=&mleft;
ptop=&mtop;
}
//结束
程序写得很个人化……