DirectDraw创建离屏表面显示

来源:互联网 发布:净值曲线软件 编辑:程序博客网 时间:2024/04/27 21:57

//  http://hi.baidu.com/yeyingxian/item/4da93f7493fd4511d0dcb3f3

 

#ifndef _DDRAWDISP_H#define _DDRAWDISP_H#include <ddraw.h>class CDDrawDisplay{public: BOOL DDrawDispInit(HWND hWnd, int src_width, int src_height, int dst_width, int dst_height); void DDrawDispReinit(HWND hWnd, int src_width, int src_height, int dst_width, int dst_height); void DDrawDispDone(); void DDrawUpdateDisp(unsigned char *src[3], int stride[3]); ~CDDrawDisplay();protected: void ConvertYUV2RGB(unsigned char *src[3], int stride[3],         unsigned char *dst, int dst_stride,         int width, int height);protected: int m_src_width; int m_src_height; int m_dst_top; int m_dst_left; int m_dst_width; int m_dst_height; HWND m_hWnd; LPDIRECTDRAW            m_lpDD;   // DirectDraw 对象指针 LPDIRECTDRAWSURFACE     m_lpDDSPrimary; // DirectDraw 主表面指针 LPDIRECTDRAWSURFACE     m_lpDDSOverlay; // DirectDraw 离屏表面指针};#endif#include <windows.h>#include "DDrawDisp.h"#pragma comment(lib,"ddraw.lib")#define GET_R(c1,su,sv) (((c1)+409*(sv))>>8)#define GET_G(c1,su,sv) (((c1)-100*(su)-208*(sv))>> 8)#define GET_B(c1,su,sv) (((c1)+516*(su))>> 8)static inline int CLIP(int value){ if (value & (~255))  value = (-value) >> 31; return value;}void CDDrawDisplay::ConvertYUV2RGB(unsigned char *src[3], int stride[3],         unsigned char *dst, int dst_stride,         int width, int height){ int wrap,wrap2,x,y; int tmp=0; int sy,su,sv; int r,g,b; int c1; unsigned char *py; wrap=stride[0]; wrap2=dst_stride; py=src[0]; for(y=0;y<height;y+=2) {  for(x=0;x<width;x+=2)  {   sy=py[0]-16;   su=*(src[1]++)-128;   sv=*(src[2]++)-128;   c1=298*(sy);   r=CLIP(GET_R(c1,su,sv));   g=CLIP(GET_G(c1,su,sv));   b=CLIP(GET_B(c1,su,sv));   *((short*)dst) = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);   sy=py[1]-16;   c1=298*(sy);   r=CLIP(GET_R(c1,su,sv));   g=CLIP(GET_G(c1,su,sv));   b=CLIP(GET_B(c1,su,sv));   *((short*)(dst+2)) = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);   sy=py[wrap]-16;   c1=298*(sy);   r=CLIP(GET_R(c1,su,sv));   g=CLIP(GET_G(c1,su,sv));   b=CLIP(GET_B(c1,su,sv));   *((short*)(dst+wrap2)) = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);   sy=py[wrap+1]-16;   c1=298*(sy);   r=CLIP(GET_R(c1,su,sv));   g=CLIP(GET_G(c1,su,sv));   b=CLIP(GET_B(c1,su,sv));   *((short*)(dst+wrap2+2)) = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);   py += 2;   dst += 4;  }  py+=2*stride[0]-width;  src[1]+=stride[1]-width/2;  src[2]+=stride[2]-width/2;  dst+=2*wrap2-width*2; }}BOOL CDDrawDisplay::DDrawDispInit(HWND hWnd, int src_width, int src_height,      int dst_width, int dst_height){ RECT rect; GetClientRect(hWnd, &rect);// rect.right = GetSystemMetrics(SM_CXSCREEN);// rect.bottom = GetSystemMetrics(SM_CYSCREEN); m_src_width = src_width; m_src_height = src_height; m_hWnd = hWnd; if (dst_width > rect.right)  dst_width = rect.right; if (dst_height > rect.bottom)  dst_height = rect.bottom; if (dst_width == -1) // Full Screen {  if (rect.right*src_height/src_width > rect.bottom)  {   dst_height = rect.bottom;   dst_width = rect.bottom * src_width / src_height;  }  else  {   dst_width = rect.right;   dst_height = rect.right * src_height / src_width;  } } m_dst_left = (rect.right-dst_width)/2; m_dst_top = (rect.bottom-dst_height)/2; m_dst_width = dst_width; m_dst_height = dst_height; // 创建DirectCraw对象 if ( DirectDrawCreate(NULL, &m_lpDD, NULL) != DD_OK )   return FALSE;   // 设置协作层 if ( m_lpDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL) != DD_OK )  return FALSE; DDSURFACEDESC   ddsd;   // DirectDraw 表面描述 // 创建主表面 ZeroMemory(&ddsd, sizeof(ddsd));    ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS ;    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; if ( m_lpDD->CreateSurface(&ddsd, &m_lpDDSPrimary, NULL) != DD_OK )  return FALSE;    // Create a offscreen bitmap.    ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;    ddsd.dwHeight = src_height;    ddsd.dwWidth = src_width; if ( m_lpDD->CreateSurface(&ddsd, &m_lpDDSOverlay, NULL) != DD_OK )  return FALSE; // Should check if the offscreen is RGB565 DDPIXELFORMAT ddpf; m_lpDDSOverlay->GetPixelFormat(&ddpf); return TRUE;}void CDDrawDisplay::DDrawDispReinit(HWND hWnd, int src_width, int src_height,        int dst_width, int dst_height){ DDrawDispDone(); DDrawDispInit(hWnd, src_width, src_height, dst_width, dst_height);}void CDDrawDisplay::DDrawDispDone(){    if (m_lpDDSOverlay != NULL)    {        m_lpDDSOverlay->Release();        m_lpDDSOverlay = NULL;    }    if (m_lpDDSPrimary != NULL)    {        m_lpDDSPrimary->Release();        m_lpDDSPrimary = NULL;    }    if (m_lpDD != NULL)    {        m_lpDD->Release();        m_lpDD = NULL;    }}CDDrawDisplay::~CDDrawDisplay(){ DDrawDispDone();}void CDDrawDisplay::DDrawUpdateDisp(unsigned char *src[3], int stride[3]){ HRESULT     hRet;   // DirectDraw 函数返回值 DDSURFACEDESC   ddsd;   // DirectDraw 表面描述    memset(&ddsd, 0, sizeof(ddsd));    ddsd.dwSize = sizeof(ddsd);     // Lock down the surface so we can modify it's contents.    hRet = m_lpDDSOverlay->Lock( NULL, &ddsd, DDLOCK_WAITNOTBUSY, NULL);    if (FAILED(hRet))  return ; LPBYTE lpSurf = (LPBYTE)ddsd.lpSurface; ConvertYUV2RGB(src, stride, lpSurf, ddsd.lPitch, m_src_width, m_src_height); m_lpDDSOverlay->Unlock(NULL); RECT rs, rd;    DDBLTFX                     ddbltfx; rs.left = rs.top = 0; rs.right = m_src_width; rs.bottom = m_src_height; rd.left = m_dst_left; rd.top = m_dst_top; rd.right = m_dst_left + m_dst_width; rd.bottom = m_dst_top + m_dst_height;    memset(&ddbltfx, 0, sizeof(ddbltfx));    ddbltfx.dwSize = sizeof(ddbltfx);    ddbltfx.dwROP = SRCCOPY; // Bitblt the offscreen to the front m_lpDDSPrimary->Blt(&rd, m_lpDDSOverlay, NULL, DDBLT_ROP, &ddbltfx);}