最简单的DDRAW C代码实现(只支持YUV420数据)

来源:互联网 发布:mac框架 编辑:程序博客网 时间:2024/05/01 20:08

#include <tchar.h>
#include <ddraw.h>

#pragma comment(lib, "dxguid.lib")

IDirectDraw7 *pIDirectDraw7;
IDirectDrawSurface7 *pIDirectDrawSurface7Primary;
IDirectDrawSurface7 *pIDirectDrawSurface7OffScreen;

DDSURFACEDESC2 tDDSurfaceDesc2;

HINSTANCE Hinstance = NULL;

BOOL UnInitDirectDrawC()
{
    if(pIDirectDraw7)
    {
        IDirectDraw7_Release(pIDirectDraw7);
        pIDirectDraw7 = NULL;
    }
    if(pIDirectDrawSurface7Primary)
    {
        IDirectDrawSurface_Release(pIDirectDrawSurface7Primary);
        pIDirectDrawSurface7Primary = NULL;
    }
    
    if(pIDirectDrawSurface7OffScreen)
    {
        IDirectDrawSurface_Release(pIDirectDrawSurface7OffScreen);
        pIDirectDrawSurface7OffScreen = NULL;
    }
    
    if(Hinstance)
    {
        FreeLibrary(Hinstance);
        Hinstance = NULL;
    }
    
    return TRUE;
}

BOOL InitDirectDrawC(HWND hWnd, int Width, int Height)
{
    HRESULT (WINAPI *ZRDirectDrawCreateEx)(GUID *lpGuid, LPVOID *lplpDD, REFIID iid, IUnknown FAR *pUnkOuter);

    IDirectDrawClipper *pcClipper = NULL;

    if((NULL == hWnd) || (0 != Width % 2) || (0 != Height % 2))
    {
        return FALSE;
    }

    do
    {
        Hinstance = LoadLibrary(_T("DDRAW.dll"));
        ZRDirectDrawCreateEx = (void *)GetProcAddress(Hinstance, _T("DirectDrawCreateEx"));
        if(ZRDirectDrawCreateEx == NULL)
        {
            break;
        }
        
        if(DD_OK != ZRDirectDrawCreateEx(NULL, (VOID**)&pIDirectDraw7, &IID_IDirectDraw7, NULL)) 
        {
            break;
        }
        
        if(DD_OK != IDirectDraw7_SetCooperativeLevel(pIDirectDraw7, hWnd, DDSCL_NORMAL | DDSCL_NOWINDOWCHANGES))
        {
            break;
        }
        
        ZeroMemory(&tDDSurfaceDesc2, sizeof(tDDSurfaceDesc2));
        tDDSurfaceDesc2.dwSize = sizeof(tDDSurfaceDesc2);
        tDDSurfaceDesc2.dwFlags = DDSD_CAPS;
        tDDSurfaceDesc2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
        if(DD_OK != IDirectDraw7_CreateSurface(pIDirectDraw7, &tDDSurfaceDesc2, &pIDirectDrawSurface7Primary, NULL))
        {
            break;
        }
        
        if(DD_OK != IDirectDraw7_CreateClipper(pIDirectDraw7, 0, &pcClipper, NULL))
        {
            break;
        }
        
        if(DD_OK != IDirectDrawClipper_SetHWnd(pcClipper, 0, hWnd))
        {
            break;
        }
        
        if(DD_OK != IDirectDrawSurface_SetClipper(pIDirectDrawSurface7Primary, pcClipper))
        {
            break;
        }
        
        if(pcClipper)
        {
            IDirectDrawClipper_Release(pcClipper);
            pcClipper = NULL;
        }
        
        ZeroMemory(&tDDSurfaceDesc2, sizeof(tDDSurfaceDesc2));
        tDDSurfaceDesc2.dwSize = sizeof(tDDSurfaceDesc2);
        tDDSurfaceDesc2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
        tDDSurfaceDesc2.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
        tDDSurfaceDesc2.dwWidth = Width;
        tDDSurfaceDesc2.dwHeight = Height;
        tDDSurfaceDesc2.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
        tDDSurfaceDesc2.ddpfPixelFormat.dwFlags = DDPF_FOURCC | DDPF_YUV;
        tDDSurfaceDesc2.ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y','V', '1', '2');
        tDDSurfaceDesc2.ddpfPixelFormat.dwYUVBitCount = 8;
        if(DD_OK != IDirectDraw7_CreateSurface(pIDirectDraw7, &tDDSurfaceDesc2, &pIDirectDrawSurface7OffScreen, NULL))
        {
            break;
        }

        return TRUE;
    }while(0);
    
    if(pcClipper)
    {
        IDirectDrawClipper_Release(pcClipper);
        pcClipper = NULL;
    }

    UnInitDirectDrawC();

    return FALSE;
}

BOOL DirectDrawC(LPBYTE pBuffer)
{
    BOOL ddRval = FALSE;
    
    int i = 0;

    LPBYTE PtrY = NULL, PtrU = NULL, PtrV = NULL, lpSurf = NULL;

    if(NULL == pBuffer)
    {
        return FALSE;
    }

    PtrY = pBuffer;
    PtrU = pBuffer + tDDSurfaceDesc2.dwWidth * tDDSurfaceDesc2.dwHeight;
    PtrV = pBuffer + tDDSurfaceDesc2.dwWidth * tDDSurfaceDesc2.dwHeight * 5 / 4; 
    lpSurf = (LPBYTE)tDDSurfaceDesc2.lpSurface;      

    do 
    {
        ddRval = IDirectDrawSurface_Lock(pIDirectDrawSurface7OffScreen, NULL, &tDDSurfaceDesc2, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
    }while(ddRval == DDERR_WASSTILLDRAWING);

    if(DD_OK != ddRval)
    {
        return FALSE;
    }

    if(lpSurf)
    {
        for(i = 0; i < (int)tDDSurfaceDesc2.dwHeight; i++)
        {
            memcpy(lpSurf, PtrY, tDDSurfaceDesc2.dwWidth);
            PtrY += tDDSurfaceDesc2.dwWidth;
            lpSurf += tDDSurfaceDesc2.lPitch;
        }
        
        for(i = 0; i < (int)tDDSurfaceDesc2.dwHeight / 2; i++)
        {
            memcpy(lpSurf, PtrV, tDDSurfaceDesc2.dwWidth / 2);
            PtrV += tDDSurfaceDesc2.dwWidth / 2; 
            lpSurf += tDDSurfaceDesc2.lPitch / 2;
        }

        for(i = 0; i < (int)tDDSurfaceDesc2.dwHeight / 2; i++)
        {
            memcpy(lpSurf, PtrU, tDDSurfaceDesc2.dwWidth / 2);
            PtrU += tDDSurfaceDesc2.dwWidth / 2;
            lpSurf += tDDSurfaceDesc2.lPitch / 2;
        }
    }

    IDirectDrawSurface_Unlock(pIDirectDrawSurface7OffScreen, NULL);

    IDirectDrawSurface_Blt(pIDirectDrawSurface7Primary, NULL, pIDirectDrawSurface7OffScreen, NULL, DDBLT_WAIT, NULL);

    return TRUE;
}