windraw2.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 2,002 行 · 第 1/5 页

CPP
2,002
字号
        {
            DeleteObject (lpwd->gdi.hPalette);
            lpwd->gdi.hPalette = NULL;
        }

        /* release DCs, if taken: */
        if (lpwd->gdi.hDC != NULL) 
        {   
            ReleaseDC (lpwd->hWnd, lpwd->gdi.hDC);   
            lpwd->gdi.hDC = NULL;   
        } 
        if (lpwd->gdi.hMemoryDC != NULL) 
        {
            DeleteDC (lpwd->gdi.hMemoryDC);
            lpwd->gdi.hMemoryDC = NULL;
        }
        if (lpwd->gdi.hMemoryDC2 != NULL) 
        {
            DeleteDC (lpwd->gdi.hMemoryDC2);
            lpwd->gdi.hMemoryDC2 = NULL;
        }
    }

    cleanup:
    /* deactivate WinDraw & exit: */
    lpwd->fMode = 0;

    /* remove display mode data */
    DeleteDisplayModes(lpwd);
    HX_DELETE(lpwd->m_pModesList);

    HX_DELETE(lpwd->m_pSurfaceList);

    DeleteCriticalSection(&lpwd->csPrimary);

    InterlockedDecrement(&g_ehandlerMutexCnt);
    if (!g_ehandlerMutexCnt)
    {
        DeleteCriticalSection(&g_ehandlerMutex);
    }
    

    
    return NOERROR;
}

/*
* Get display/primary surface format.
* Use:
*  HRESULT WinDraw2_GetDisplayFormat (LPWINDRAW lpwd, LPBMI lpbiDisplayFormat);
* Input:
*  lpwd - pointer to a WINDRAW structure to initialize
*  lpbiDisplayFormat - a structure to contain display format
* Returns:
*  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
*/
HRESULT WinDraw2_GetDisplayFormat (LPWINDRAW lpwd, LPBMI lpbiDisplayFormat)
{
    int sz;
    
    /* check parameters: */
    if (lpwd == NULL || !(lpwd->fMode & WINDRAW_OPENED) ||
        lpbiDisplayFormat == NULL)
        return E_INVALIDARG;
    
    /* check the size of BITMAPINFO structure to copy: */
    sz = lpbiDisplayFormat->bmiHeader.biSize;
    if (sz < (int)sizeof(BITMAPINFOHEADER) || sz > (int)lpwd->bmiDisplayFormat.bmiHeader.biSize)
        sz = lpwd->bmiDisplayFormat.bmiHeader.biSize;
    
    /* copy bitmap info: */
    
    /* Since it seems that our convention was to set biSize to the sizeof 
    * BITMAPINFOHEADER instead of the actual size of the structure (which
    * causes us to lose the color table of bit fields) we will use the size
    * of the structure.
    */
    // memcpy(lpbiDisplayFormat, &(lpwd->bmiDisplayFormat), sz);
    GetDisplayFormat(&lpwd->bmiDisplayFormat, lpwd->lpszDisplayDevice);
    
    memcpy(lpbiDisplayFormat, &(lpwd->bmiDisplayFormat), sizeof(BMI) ); /* Flawfinder: ignore */
    
    return NOERROR;
}

/*
* GDISURFACE functions:
*/
#define hMEMORY ((HANDLE) 0xFFFFFFFF)   /* says to open as memory file  */

/*
* This function allocates a shared memory block for use by the source filter
* generating DIBs for us to render. The memory block is created in shared
* memory so that GDI doesn't have to copy the memory when we do a BitBlt
*/
static LPGDISURFACE GDISurface_Alloc (LPBITMAPINFO pbmi)
{
    LPGDISURFACE lpGDISurface;  /* pointer to a new GDISURFACE  */
    HANDLE      hMapping;       /* handle to mapped object      */
    HBITMAP     hBitmap;        /* DIB section bitmap handle    */
    BYTE        *pBase;         /* pointer to the actual image  */
    
    /* allocate a new GDISURFACE structure to use: */
    lpGDISurface = (LPGDISURFACE)malloc (sizeof (GDISURFACE));
    if (lpGDISurface != NULL) {
	
        /* create a file mapping object and map into our address space: */
        hMapping = CreateFileMapping (hMEMORY, NULL, PAGE_READWRITE, (DWORD) 0, pbmi->bmiHeader.biSizeImage, NULL);
        if (hMapping != NULL) {
	    
            /* create a DIB section using given image format */
            hBitmap = CreateDIBSection ((HDC) NULL, pbmi, DIB_RGB_COLORS, (VOID **) &pBase, hMapping, (DWORD) 0);
            if (hBitmap != NULL && pBase != NULL) {
		
                /* initialise the GDISURFACE structure: */
                lpGDISurface->hBitMap = hBitmap;
                lpGDISurface->hMapping = hMapping;
                lpGDISurface->lpBase = pBase;
                lpGDISurface->lpAlphaSurface = NULL;
                lpGDISurface->hEmpty = CreateEvent(NULL, TRUE, TRUE, NULL);
                
                /* lpGDISurface->PaletteVersion = PALETTE_VERSION; */
                GetObject (hBitmap, sizeof (DIBSECTION), (VOID *)& (lpGDISurface->DibSection));
		
                /* success: */
                return lpGDISurface;
            }
            /* close file mapping... */
            CloseHandle (hMapping);
        }
        /* free buffer: */
        free (lpGDISurface);
    }
    return NULL;
}

/*
* Releases previously allocated GDI buffer.
* Main application should consider calling GdiFlush ();
* before releasing these buffers.
*/
static void GDISurface_Free (LPGDISURFACE lpGDISurface)
{
    /* check pointer to a buffer structure to use: */
    if (lpGDISurface != NULL) {
        /* close dibsection: */
        DeleteObject (lpGDISurface->hBitMap);
        /* close file mapping: */
        CloseHandle (lpGDISurface->hMapping);
        /* close alpha channel */
        free(lpGDISurface->lpAlphaSurface);
        /* close event */
        CloseHandle(lpGDISurface->hEmpty);
        /* free buffer: */
        free (lpGDISurface);
    }
}

static BOOL GDISurface_AlphaBltIndirect(LPWINDRAW lpwd, LPGDISURFACE lpGDISurfaceDest,
					LPGDISURFACE lpGDISurfaceSrc, LPRECT lpDestRect, LPRECT lpSrcRect)
{
#if 0     
    INT32 destX, destY;
    INT32 destStride, srcStride, alphaStride;
    UINT32 *srcBuf, *destBuf;
    UCHAR  *alphaBuf;
    UCHAR alpha, invalpha;
    UCHAR *pSrc, *pDest;
    
    int destCID = GetBitmapColor((LPBITMAPINFO) &lpGDISurfaceDest->DibSection.dsBmih);
    int srcCID  = GetBitmapColor((LPBITMAPINFO) &lpGDISurfaceSrc->DibSection.dsBmih);
    
    assert(destCID == srcCID); // not supported
    
    switch (destCID)
    {
    case CID_RGB565:
    case CID_RGB555:
	destStride  = (lpGDISurfaceDest->DibSection.dsBmih.biWidth - (lpDestRect->right - lpDestRect->left)) * 2;
	srcStride   = (lpGDISurfaceSrc->DibSection.dsBmih.biWidth - (lpSrcRect->right - lpSrcRect->left)) * 2;
	srcBuf	    = (UINT32*)(lpGDISurfaceSrc->lpBase + ( (lpSrcRect->right - lpSrcRect->left) * lpSrcRect->top 
	    + lpSrcRect->left ) * 2);
	destBuf	    = (UINT32*)(lpGDISurfaceDest->lpBase + ( (lpDestRect->right - lpDestRect->left) * lpDestRect->top 
	    + lpDestRect->left) *2);
	break;
    case CID_RGB32:
	destStride  = (lpGDISurfaceDest->DibSection.dsBmih.biWidth - (lpDestRect->right - lpDestRect->left)) * 4;
	srcStride   = (lpGDISurfaceSrc->DibSection.dsBmih.biWidth - (lpSrcRect->right - lpSrcRect->left)) * 4;
	srcBuf	    = (UINT32*)(lpGDISurfaceSrc->lpBase + ( (lpSrcRect->right - lpSrcRect->left) * lpSrcRect->top 
	    + lpSrcRect->left ) *4);
	destBuf	    = (UINT32*)(lpGDISurfaceDest->lpBase + ( (lpDestRect->right - lpDestRect->left) * lpDestRect->top 
	    + lpDestRect->left ) *4);
	break;
    case CID_RGB24:
	break;
    default:
	assert(CID_NOTSUPPORTED);
    }
    
    alphaBuf	= lpGDISurfaceSrc->lpAlphaSurface;
    alphaStride = lpGDISurfaceDest->DibSection.dsBmih.biWidth - (lpSrcRect->right - lpSrcRect->left);
    
    switch (destCID)
    {
    case CID_RGB32:
	{
	    for (destY = lpDestRect->top; destY < lpDestRect->bottom; destY++ )
	    {
		for (destX = lpDestRect->left;destX < lpDestRect->right;destX++, srcBuf++, destBuf++, alphaBuf++)
		{
		    alpha = *alphaBuf>128 ? *alphaBuf + 1 : *alphaBuf;
		    invalpha = 256 - alpha;
		    *destBuf = 
			((((*srcBuf	& 0x00ff0000) * alpha)	    >> 8 ) & 0x00ff0000) +
			((((*destBuf    & 0x00ff0000) * invalpha)   >> 8 ) & 0x00ff0000) +
			((((*srcBuf	& 0x0000ff00) * alpha)	    >> 8 ) & 0x0000ff00) +
			((((*destBuf    & 0x0000ff00) * invalpha)   >> 8 ) & 0x0000ff00) +
			((((*srcBuf	& 0x000000ff) * alpha)	    >> 8 ) & 0x000000ff) +
			((((*destBuf    & 0x000000ff) * invalpha)   >> 8 ) & 0x000000ff);
		}						  
		destBuf	    += destStride;
		srcBuf	    += srcStride;
		alphaBuf    += alphaStride;
	    }
	    break;
	}
    case CID_RGB24:
	{
	    pSrc    = lpGDISurfaceSrc->lpBase;
	    pDest   = lpGDISurfaceDest->lpBase;
	    pDest   += (lpGDISurfaceDest->DibSection.dsBmih.biWidth * (lpGDISurfaceDest->DibSection.dsBmih.biHeight - lpDestRect->top) + lpDestRect->left)* 3;
	    pSrc    += (lpGDISurfaceSrc->DibSection.dsBmih.biWidth * (lpGDISurfaceSrc->DibSection.dsBmih.biHeight - lpSrcRect->top) + lpSrcRect->left)* 3;
	    
	    for (destY = lpDestRect->top; destY < lpDestRect->bottom; destY++ )
	    {
		for (destX = lpDestRect->left;destX < lpDestRect->right;destX++, alphaBuf++)
		{   
		    //		    alpha	= *alphaBuf;
		    alpha	= 128;
		    invalpha	= 256 - alpha;
		    
		    *pDest = (*pSrc * alpha) >> 8 + (*pDest * invalpha) >> 8;
		    pDest++; pSrc++;
		    *pDest = (*pSrc * alpha) >> 8 + (*pDest * invalpha) >> 8;
		    pDest++; pSrc++;
		    *pDest = (*pSrc * alpha) >> 8 + (*pDest * invalpha) >> 8;
		    pDest++; pSrc++;
		}
		pDest -= (lpGDISurfaceDest->DibSection.dsBmih.biWidth + (lpDestRect->right - lpDestRect->left))*3;
		pSrc -= (lpGDISurfaceSrc->DibSection.dsBmih.biWidth + (lpSrcRect->right - lpSrcRect->left))*3;
		alphaBuf +=alphaStride;
	    }
	    break;
	}
	
    case CID_RGB565:
    case CID_RGB555:
	{
	/*
	* The following bugs are plain (and all stem from the same problem)
	*
	*	1. If the dest/src rects are not both even.
	*  2. If the width of the blt is not even
	* 
	    */
	    for (destY = lpDestRect->top; destY < lpDestRect->bottom; destY++ )
	    {
		for (destX = lpDestRect->left;destX < lpDestRect->right;destX+=2, srcBuf++, destBuf++, alphaBuf++)
		{
		    alpha	= *alphaBuf>128 ? *alphaBuf + 1 : *alphaBuf;
		    invalpha	= 256 - alpha;
		    *destBuf = 
			((((*srcBuf	& 0xf8000000) * alpha)	    >> 8 ) & 0xf8000000) +
			((((*destBuf    & 0xf8000000) * invalpha)   >> 8 ) & 0xf8000000) +
			((((*srcBuf	& 0x07e00000) * alpha)	    >> 8 ) & 0x07e00000) +
			((((*destBuf    & 0x07e00000) * invalpha)   >> 8 ) & 0x07e00000) +
			((((*srcBuf	& 0x001f0000) * alpha)	    >> 8 ) & 0x001f0000) +
			((((*destBuf    & 0x001f0000) * invalpha)   >> 8 ) & 0x001f0000) +
			((((*srcBuf	& 0x0000f800) * alpha)	    >> 8 ) & 0x0000f800) +
			((((*destBuf    & 0x0000f800) * invalpha)   >> 8 ) & 0x0000f800) +
			((((*srcBuf	& 0x000007e0) * alpha)	    >> 8 ) & 0x000007e0) +
			((((*destBuf    & 0x000007e0) * invalpha)   >> 8 ) & 0x000007e0) +
			((((*srcBuf	& 0x0000001f) * alpha)	    >> 8 ) & 0x0000001f) +
			((((*destBuf    & 0x0000001f) * invalpha)   >> 8 ) & 0x0000001f);
		}
		destBuf	    += destStride;
		srcBuf	    += srcStride;
		alphaBuf    += alphaStride;
	    }
	    break;
	}
    }
#endif
    return NOERROR;
}

/*
* Blits image data into the window.
* Use:
*  BOOL DDSurface_BltIndirect(LPWINDRAW lpwd, LPGDISURFACE lpGDISurface,
*       LPRECT lpSourceRect, LPRECT lpTargetRect)
* Input:
*  lpwd - pointer to the WINDRAW structure
*  lpDDSurfaceSrc - a structure containing DIBSECTION of image to blit
*  lpDDSurfaceDst - a 
*  lpSrcRect - a source image region to blit
*  lpDstRect - a target window region to fill with image
* Returns:
*  TRUE, if success; FALSE, otherwise.
*/
static BOOL DDSurface_BltIndirect(  
				  LPWINDRAW lpwd, 
				  LPDIRECTDRAWSURFACE lpDDSurfaceDst,
				  LPDIRECTDRAWSURFACE lpDDSurfaceSrc, 
				  LPRECT lpDstRect, 
				  LPRECT lpSrcRect
				  )
{
    /* 
    * this will currently only work if the two color formats are 
    * the same.
    */
    
    /* set update mode: */
    DWORD dwFlags = DDBLT_WAIT | DDBLT_ROP;
    
    /* set effects: */
    DDBLTFX ddBltFx;
    ZeroMemory(&ddBltFx, sizeof(DDBLTFX));
    ddBltFx.dwSize  = sizeof (DDBLTFX);
    ddBltFx.dwROP   = SRCCOPY;
    
    /* try to blit data from an offscreen surface: */
    HRESULT retVal;

    try
    {
    
    retVal = lpDDSurfaceDst->Blt(lpDstRect, lpDDSurfaceSrc, lpSrcRect, dwFlags, &ddBltFx);

    }
    catch(...)
    {
        char szTmp[256]; /* Flawfinder: ignore */
        sprintf(szTmp, "DDSurface_BltIndirect srcRect %ld %ld %ld %ld dstRc %ld %ld %ld %ld", /* Flawfinder: ignore */
                       lpSrcRect->left, lpSrcRect->top, lpSrcRect->right, lpSrcRect->bottom,
                       lpDstRect->left, lpDstRect->top, lpDstRect->right, lpDstRect->bottom);

        DumpDDInfo(lpwd, lpDDSurfaceDst, "DDSurface_BltIndirect");
        retVal = HXR_FAIL;
    }

    return retVal;
}

/*
* Blits image data into the window.
* Use:
*  BOOL GDISurface_BltIndirect(LPWINDRAW lpwd, LPGDISURFACE lpGDISurface,
*       LPRECT lpSourceRect, LPRECT lpTargetRect)
* Input:
*  lpwd - pointer to the WINDRAW structure
*  lpGDISurface - a structure containing DIBSECTION of image to blit
*  lpSourceRect - a source image region to blit
*  lpTargetRect - a target window region to fill with image
* Returns:
*  TRUE, if success; FALSE, otherwise.
*/
static BOOL GDISurface_BltIndirect(LPWINDRAW lpwd, LPGDISURFACE lpGDISurfaceDest,
				   LPGDISURFACE lpGDISurfaceSrc, LPRECT lpSourceRect, LPRECT lpTargetRect)
{
    
    BOOL bResult;                   /* return value             */
    /* get sizes of source/destination rectangles: */
    LONG lTargetWidth  = lpTargetRect->right  - lpTargetRect->left;
    LONG lTargetHeight = lpTargetRect->bottom - lpTargetRect->top;
    LONG lSourceWidth  = lpSourceRect->right  - lpSourceRect->left;
    LONG lSourceHeight = lpSourceRect->bottom - lpSourceRect->top;
    
    /* select bitmap to blit: */
    HBITMAP hOldBitmap	= (HBITMAP) SelectObject (lpwd->gdi.hMemoryDC, lpGDISurfaceDest->hBitMap);
    HBITMAP hOldBitmap2 = (HBITMAP) SelectObject (lpwd->gdi.hMemoryDC2, lpGDISurfaceSrc->hBitMap);
    
    if (lpGDISurfaceSrc->lpAlphaSurface)
    {
	return GDISurface_AlphaBltIndirect(lpwd, lpGDISurfaceDest, lpGDISurfaceSrc, lpTargetRect, lpSourceRect);
    }
    
    /* is the window the same size as the video: */
    if (lTargetWidth == lSourceWidth && lTargetHeight == lSourceHeight) 
    {
        /* put the image straight into the destination: */
        bResult = BitBlt (
            lpwd->gdi.hMemoryDC,    /* target device HDC        */
            lpTargetRect->left,     /* x sink position          */
            lpTargetRect->top,      /* y sink position          */
            lTargetWidth,           /* destination width        */
      

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?