知了博客

集天地之精华,吸日月之灵气

« 史玉柱PK魅族黄章 到底谁更牛?VS2005调试断点不起作用的解决方法 »

DirectDraw简单用法

GDI:win32 gdi 与 DirectDraw 操作DIB的,DirectDraw 直接操作内存。

//ce 6下面测试:
IDirectDraw *pDraw;
IDirectDrawSurface *pDFace;
IDirectDrawSurface *pLayer;
HRESULT hr;
DDSURFACEDESC  ddsd;

  RECT rect;
  dlgMain.GetWindowRect(&rect);
  DirectDrawCreate(NULL, &pDraw, NULL);
  pDraw->SetCooperativeLevel(dlgMain,DDSCL_NORMAL);
  ddsd.dwSize = sizeof(ddsd);
  ddsd.dwFlags = DDSD_CAPS;
  ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  hr = pDraw->CreateSurface(&ddsd, &pDFace,NULL);

  DDCAPS ddcaps;
  memset(&ddcaps, 0, sizeof(ddcaps));
  hr = pDraw->GetCaps(&ddcaps,NULL);
  

  memset(&ddsd, 0, sizeof(ddsd));
  ddsd.dwSize = sizeof(ddsd);
  ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
  ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH |DDSD_PIXELFORMAT;
  ddsd.dwWidth = 800;
  ddsd.dwHeight = 480;
  ddsd.ddpfPixelFormat = ddpfOverlayFormats;

  hr = pDraw->CreateSurface(&ddsd, &pLayer,NULL);

  hr = pLayer->IsLost();
 
  DDOVERLAYFX ofx;
  memset(&ofx, 0, sizeof(DDOVERLAYFX));
  ofx.dwSize = sizeof(DDOVERLAYFX);
  ofx.dckSrcColorkey.dwColorSpaceLowValue = 0x0000F81F;
  ofx.dckSrcColorkey.dwColorSpaceHighValue = 0x0000;
  ofx.dwAlphaConstBitDepth = 8;
  ofx.dwAlphaConst = 0x50;
  RECT rt1= {0,0,400,480};
  hr = pLayer->UpdateOverlay(&rt1, pDFace, &rt1,DDOVER_SHOW|DDOVER_KEYSRCOVERRIDE, &ofx);

  HDC hdc;
  hr = pLayer->GetDC(&hdc);
  FillRect(hdc,&rt1, (HBRUSH)GetStockObject(BLACK_BRUSH));
  SetBkColor(hdc,TRANSPARENT);
  SetTextColor(hdc,0x0000F81F);
  DrawText(hdc,_T("pLayerpLayer pLayervpLayer "), -1,  &rt1, 1);
  hr = pLayer->ReleaseDC(hdc);
   pLayer->Release();
   pDFace->Release();
   pDraw->Release();


1.链接库

动态装载
typedef HRESULT (* DIRECTDRAWCREATE)( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter );
m_hModule=::LoadLibrary(_T("ddraw.dll"));
m_pDirectDrawCreate= (DIRECTDRAWCREATE)::GetProcAddress(m_hModule,L"DirectDrawCreate");

静态链接
#pragma comment(lib, "ddraw.lib") 调用DirectDrawCreate

2.GUID的使用

直接定义
const GUID g_IID_IDirectDraw ={0x9c59509a,0x39bd,0x11d1,
0x8c,0x4a,0x00,0xc0,0x4f,0xd9,0x30,0xc5};

链接#pragma comment(lib, "dxguid.lib")
QueryInterface IID_IDirectDraw4

3.创建主页面

// Create the main DirectDraw object
LPDIRECTDRAW g_pDD;
hRet = DirectDrawCreate(NULL, &g_pDD, NULL);
hRet = g_pDD->QueryInterface(g_IID_IDirectDraw, (LPVOID *)&g_pDD);
// Get normal mode
hRet = g_pDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);

memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
// creates a DirectDrawSurface object for this DirectDraw object.
hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL);
创建主页面无须指定像素格式和页面大小

4.页面的像素格式

//YUV4:1:1
DDPIXELFORMAT pixel_format=
{sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y','V','1','2'),0,0,0,0,0};

//RGB565
DDPIXELFORMAT ddpfOverlayFormats =
{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0xF800, 0x07e0, 0x001F, 0};

5.创建OverLay页面

memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_BACKBUFFERCOUNT | DDSD_PIXELFORMAT;
ddsd.dwWidth = DDRAW_X;
ddsd.dwHeight = DDRAW_Y;
ddsd.dwBackBufferCount = 1;//有个后台页面
ddsd.ddpfPixelFormat = pixel_format;

hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSOverlay, NULL);
创建OverLay页面应该指定页面的大小(可以全屏),像素格式。

6.OverLay页面的显示与隐藏
void ShowOverLay()
{
DDOVERLAYFX ovfx = {0};
ovfx.dwSize = sizeof(DDOVERLAYFX);
ovfx.dckSrcColorkey.dwColorSpaceLowValue = COLOR_KEY;//指定页面的透明色
ovfx.dckSrcColorkey.dwColorSpaceHighValue = COLOR_KEY;
ovfx.dwAlphaConstBitDepth = 8;//指明alpha位宽度
ovfx.dwAlphaConst = 0x50;//alpha透明值 指明页面的透明度.16级.

RECT rs;
rs.left = 0;
rs.top = 0;
rs.right = DDRAW_X;
rs.bottom = DDRAW_Y;

DWORD dwUpdateFlags = DDOVER_KEYSRCOVERRIDE | DDOVER_SHOW;
if(g_pDDSOverlay != NULL && g_pDDSOverlay->IsLost() == DD_OK)
{
HRESULT hret = g_pDDSOverlay->UpdateOverlay(&rs,g_pDDSPrimary,&rs,dwUpdateFlags,&ovfx);
//将主页面和OverLay页面关联起来
if(hret != DD_OK)
{
printf("Update OverLay errorrn");
if(hret == DDERR_SURFACELOST)
{
g_pDDSOverlay->Restore();
}
}
}
}

dwUpdateFlags = DDOVER_HIDE即隐藏页面。
UpdateOverlay这个接口一般是在页面初始化后,显示,隐藏这三种状况下调用,
每次在页面上绘图后不必要调用UpdateOverlay,否则就会造成画面显示卡动,不连续。

7.在页面上绘图

在页面上绘图有两种方法
一是获取页面DC后,以GDI方式绘图
if( g_pDDSOverlay->GetDC(&hDC) == DD_OK)
//进行DC绘图
g_pDDSOverlay->ReleaseDC(hDC);
第二种状况当知道页面的像素格式,Lock页面获取页面指针,直接操作页面存储区。
g_pDDSOverlay->Lock(NULL,&ddsd,0,NULL);
BYTE *pFramePhyPtr = (LPBYTE)ddsd.lpSurface;
int framesize = DDRAW_X * DDRAW_Y;
memcpy(pFramePhyPtr,src[0],framesize);
memcpy(pFramePhyPtr + framesize,src[2],framesize / 4);
memcpy(pFramePhyPtr + framesize + framesize / 4,src[1], framesize / 4);
g_pDDSOverlay->Unlock(NULL);//YUV4:1:1

8.遍历后台页面

EnumAttachedSurfaces
enumerates all the surfaces attached to a given primary surface.
可以先到后台页面上绘制,然后Flip操作.

9.注意要点
不要频繁调用UpdateOverLay。
注意页面的像素格式与图像帧的像素格式的匹配,
为了加快显示速度,最好与显示驱动所支持的像素格式相同。
可以用后台页面和Flip操作,加快页面显示。

具体操作见资源中心的示例。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

日历

最新评论及回复

最近发表

Powered By Z-Blog 1.8 Arwen Build 90619 Code detection by Codefense  theme by BokeZhuti

Copyright know blog. Some Rights Reserved.站长(msn):webmaster#webgou.info(#换成@) 粤ICP备09183716号