www.pudn.com > DualDisplay.rar > DisplayConfig.cpp


/****************************************************************************** 
** Copyright (C) 2004. Intel Corporation. All Rights Reserved.  
** 
** The source code contained or described herein and all documents related to the 
** source code ("Material") are owned by Intel Corporation or its suppliers or  
** licensors. Title to the Material remains with Intel Corporation or its suppliers 
** and licensors. The Material contains trade secrets and proprietary and  
** confidential information of Intel or its suppliers and licensors. The Material  
** is protected by worldwide copyright and trade secret laws and treaty provisions. 
** No part of the Material may be used, copied, reproduced, modified, published,  
** uploaded, posted, transmitted, distributed, or disclosed in any way without  
** Intel’s prior express written permission. 
**  
** No license under any patent, copyright, trade secret or other intellectual  
** property right is granted to or conferred upon you by disclosure or delivery  
** of the Materials, either expressly, by implication, inducement, estoppel or  
** otherwise. Any license under such intellectual property rights must be express  
** and approved by Intel in writing. 
******************************************************************************/ 
// DisplayConfig.cpp: implementation of the CDisplayConfig class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "DispDemo1.h" 
#include "DisplayConfig.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
 
extern "C" BOOL VirtualCopy(  
	LPVOID lpvDest,  
	LPVOID lpvSrc,  
	DWORD cbSize,  
	DWORD fdwProtect  
	); 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CDisplayConfig::CDisplayConfig() 
{ 
	m_hdcMarathon = GetDC(NULL); 
	m_hdcXScale = CreateDC(L"ddi.dll", NULL, NULL, NULL); 
	memset(&m_RFBDesktop, 0, sizeof(RawFrameBufferInfo)); 
	memset(&m_RFBXScale, 0, sizeof(RawFrameBufferInfo)); 
	memset(&m_RFBSecondary, 0, sizeof(RawFrameBufferInfo)); 
	m_pBufDesktop = NULL; 
	m_pBufXScale = NULL; 
	m_pBufSecondary = NULL; 
 
 
 
	m_hbmSecondary = NULL; 
	m_hdcSecondaryMem = NULL; 
	 
	AcquireLock(TRUE); 
 
	// get info about desktop surface, so we can save the rotation 
	DISPCFG_GET_SURFACE_INFO surfinfo; 
	surfinfo.eDisplaySurface = DCFG_DESKTOP; 
 
	int nEscRtn = ExtEscape(m_hdcMarathon,  
					  DRVESC_GET_SURFACEINFO,  
					  sizeof(DISPCFG_GET_SURFACE_INFO), 
					  (LPSTR) &surfinfo, 
					  sizeof(DISPCFG_GET_SURFACE_INFO), 
					  (LPSTR) &surfinfo); 
	if (0 > nEscRtn) 
	{ 
		TRACE(L"\n\rCDisplayConfig constructor************* DRVESC_GET_SURFACEINFO Failed!!!  Returned %d**********\n\r", nEscRtn); 
	} 
 
	m_dwOrigPhysRotation = surfinfo.sPhysSurfaceInfo.lPhysicalRotation; 
} 
 
CDisplayConfig::~CDisplayConfig() 
{ 
	FreeMarathonFrameBufferResources(); 
	if (m_pBufSecondary)  
	{ 
	    VirtualFree(m_pBufSecondary, 0, MEM_RELEASE); 
	} 
 
	if (m_pBufXScale)  
	{ 
	    VirtualFree(m_pBufXScale, 0, MEM_RELEASE); 
	} 
	 
	if (m_pBufDesktop)  
	{ 
	    VirtualFree(m_pBufDesktop, 0, MEM_RELEASE); 
	} 
	 
	AcquireLock(FALSE); 
    if (m_hdcMarathon) 
    { 
        ReleaseDC(NULL, m_hdcMarathon); 
        m_hdcMarathon = NULL; 
    } 
} 
 
void CDisplayConfig::SetInternalSource(DCFG_LCD_SOURCE eSource) 
{ 
	DISPCFG_DISPLAY_SYSTEM cfg; 
	memset(&cfg, 0, sizeof(DISPCFG_DISPLAY_SYSTEM)); 
 
	cfg.bSet = 1; 
	cfg.sLcdInternal.bValid = TRUE; 
	cfg.sLcdInternal.bActivate = (DCFG_SOURCE_NOT_APPLICABLE==eSource) ? FALSE : TRUE; 
	cfg.sLcdInternal.eLcdSource = eSource; 
	cfg.sConnectSurface.eSurface = DCFG_DESKTOP; 
	cfg.sConnectSurface.ulPhysRotation = m_dwOrigPhysRotation; 
	cfg.sConnectSurface.ulRefreshRate = 60; 
 
#if 0 
	// hack for Carbonado demos 
	// If setting intenral to be Marathon, drive it out exteranl as well 
	// This can only be done on devices that use a panel that accelpts the 
	// same display timings as the external display.  Most do not. 
 
	if (eSource == DCFG_SOURCE_MARATHON) 
	{ 
		cfg.sLcdExternal.bValid = TRUE; 
		cfg.sLcdExternal.bActivate = TRUE; 
		cfg.sLcdExternal.eLcdSource = DCFG_SOURCE_MARATHON; 
	} 
#endif 
 
	int nEscRtn = ExtEscape( 
		m_hdcMarathon, 
		DRVESC_CONFIG_DISPLAYSYSTEM,  
		sizeof(DISPCFG_DISPLAY_SYSTEM), 
		(LPSTR) &cfg, 
		0, 
		NULL); 
 
    if (0 >nEscRtn) 
	{ 
		TRACE(L"\n\rCDisplayConfig::SetInternalSource - Trying to set to %s\n\r ****DRVESC_CONFIG_DISPLAYSYSTEM Failed!!! Returned %d**********\n\r",  
			(eSource==DCFG_SOURCE_MARATHON) ? L"Marathon":L"XScale", 
			nEscRtn); 
		return; 
	} 
} 
 
void CDisplayConfig::SetExternalSource(DCFG_LCD_SOURCE eSource) 
{ 
	DISPCFG_DISPLAY_SYSTEM cfg; 
	memset(&cfg, 0, sizeof(DISPCFG_DISPLAY_SYSTEM)); 
 
	cfg.bSet = 1; 
	cfg.sLcdExternal.bValid = TRUE; 
	cfg.sLcdExternal.bActivate = (DCFG_SOURCE_NOT_APPLICABLE==eSource) ? FALSE : TRUE; 
	cfg.sLcdExternal.eLcdSource = eSource; 
	cfg.sLcdExternal.eXScaleFormat = (DCFG_SOURCE_NOT_APPLICABLE==eSource) ? DCFG_FORMAT_NOT_APPLICABLE : DCFG_LCD_IN_565 ; 
	cfg.sConnectSurface.eSurface = (DCFG_SOURCE_NOT_APPLICABLE==eSource) ? DCFG_DESKTOP : DCFG_SECONDARYSURFACE; 
	cfg.sConnectSurface.ulPhysRotation = 0; // don't really need to re-state this, since the memset allready zero'd the struct 
 
	int nEscRtn = ExtEscape( 
		m_hdcMarathon, 
		DRVESC_CONFIG_DISPLAYSYSTEM,  
		sizeof(DISPCFG_DISPLAY_SYSTEM), 
		(LPSTR) &cfg, 
		0, 
		NULL); 
 
	if (0 >nEscRtn) 
	{ 
		TRACE(L"\n\rCDisplayConfig::SetExternalSource - Trying to set to %s\n\r ****DRVESC_CONFIG_DISPLAYSYSTEM Failed!!! Returned %d**********\n\r",  
			(eSource==DCFG_SOURCE_MARATHON) ? L"Marathon":L"XScale", 
			nEscRtn); 
		return; 
	} 
} 
 
 
HDC CDisplayConfig::CreateSecondMarathonHDC(WORD wWidth, WORD wHeight) 
{ 
	if (CreateMarathonFrameBuffer(wWidth, wHeight)) 
	{ 
		return m_hdcSecondaryMem; 
	} 
	return NULL; 
} 
 
RawFrameBufferInfo* CDisplayConfig::CreateMarathonFrameBuffer(WORD wWidth, WORD wHeight) 
{	 
 
	if (m_pBufSecondary) 
	{ 
		TRACE(L"\n\rCDisplayConfig::CreateMarathonFrameBuffer\n\r ** Secondary Frame Buffer already existed!!!!****\n\r"); 
		ASSERT(NULL == m_pBufSecondary); 
	} 
	 
	// alloc external buffer / surface 
	DISPCFG_CREATE_SURFACE sCreateSurface; 
	sCreateSurface.wWidth = wWidth; 
	sCreateSurface.wHeight = wHeight; 
	 
	int nEscRtn = ExtEscape(m_hdcMarathon,  
					   DRVESC_CREATE_OFFSCREENSURFACE,  
					   sizeof(DISPCFG_CREATE_SURFACE), 
					   (LPSTR) &sCreateSurface, 
					   0, 
					   NULL); 
	if (0 >nEscRtn) 
	{ 
		TRACE(L"\n\rCDisplayConfig::SetExternalCustom\n\r ************* DRVESC_CREATE_OFFSCREENSURFACE Failed!!!  Returned %d**********\n\r", nEscRtn); 
		return NULL; 
	} 
 
	// Create (Allocate) the secondary surface 
	m_hdcSecondaryMem = CreateCompatibleDC(m_hdcMarathon); 
    m_hbmSecondary = CreateCompatibleBitmap(m_hdcMarathon, wWidth, wHeight); 
	m_hbmOldBitmap = (HBITMAP)GetCurrentObject(m_hdcSecondaryMem, OBJ_BITMAP); 
    SelectObject(m_hdcSecondaryMem, m_hbmSecondary); 
 
	// provide info about surface 
	DISPCFG_GET_SURFACE_INFO surfinfo; 
	surfinfo.eDisplaySurface = DCFG_SECONDARYSURFACE; 
 
	nEscRtn = ExtEscape(m_hdcMarathon,  
					  DRVESC_GET_SURFACEINFO,  
					  sizeof(DISPCFG_GET_SURFACE_INFO), 
					  (LPSTR) &surfinfo, 
					  sizeof(DISPCFG_GET_SURFACE_INFO), 
					  (LPSTR) &surfinfo); 
	if (0 >nEscRtn) 
	{ 
		TRACE(L"\n\rCDisplayConfig::SetExternalCustom ************* DRVESC_GET_SURFACEINFO Failed!!!  Returned %d**********\n\r", nEscRtn); 
		return NULL; 
	} 
 
	m_pBufSecondary = ConvertSurfaceInfoToRawFrameBuffer(surfinfo, m_RFBSecondary); 
	return &m_RFBSecondary; 
} 
 
void CDisplayConfig::FreeMarathonFrameBufferResources() 
{ 
	if (m_pBufSecondary) 
	{ 
        SelectObject(m_hdcSecondaryMem, m_hbmOldBitmap); 
        DeleteObject(m_hbmSecondary); 
        m_hbmSecondary = NULL; 
	    DeleteDC(m_hdcSecondaryMem); 
        m_hdcSecondaryMem = NULL; 
	} 
} 
 
 
void CDisplayConfig::AcquireLock(BOOL bAcquire) 
{ 
	int nEscRtn; 
	DISPCFG_ACQUIRE_LOCK LockIn; 
	DISPCFG_ACQUIRE_LOCK LockOut; 
	memset(&LockIn, 0, sizeof(DISPCFG_ACQUIRE_LOCK)); 
	memset(&LockOut, 0, sizeof(DISPCFG_ACQUIRE_LOCK)); 
 
	if (bAcquire) 
	{ 
		LockIn.bAcquire = TRUE; 
	} 
	else 
	{ 
		LockIn.bRelease = TRUE; 
	} 
 
	nEscRtn = ExtEscape(m_hdcMarathon,  
					  DRVESC_ACQUIRE_DUALDISPLAY, 
					  sizeof(DISPCFG_ACQUIRE_LOCK),  
					  (LPSTR)&LockIn,  
					  sizeof(DISPCFG_ACQUIRE_LOCK),(LPSTR)&LockOut); 
	if (0 >nEscRtn) 
	{ 
		TRACE(L"\n\rCDisplayConfig::AcquireLock\n\r ************* DRVESC_ACQUIRE_DUALDISPLAY Failed!!!  Returned %d**********\n\r", nEscRtn); 
		return; 
	} 
 
	TRACE(L"\n\rCDisplayConfig::AcquireLock %s success = %d\n\r", bAcquire ? L"Lock" : L"Unlock", LockOut.bSuccess); 
} 
 
DWORD CDisplayConfig::GetCurrentOSOrientation() 
{ 
	DEVMODE	sDevMode; 
	memset(&sDevMode, 0, sizeof (DEVMODE)); 
	sDevMode.dmSize = sizeof (DEVMODE); 
	ChangeDisplaySettingsEx(NULL, &sDevMode, NULL, 0, NULL); 
	return sDevMode.dmDisplayOrientation; 
} 
 
 
void CDisplayConfig::CopyDesktopToXScale() 
{ 
	GetDesktopFrameBuffer(); 
	GetXScaleFrameBuffer(); 
 
	ASSERT(m_pBufDesktop); 
	ASSERT(m_pBufXScale); 
 
	// TODO, rotation!!! 
	memcpy(m_pBufXScale,  
		   m_pBufDesktop,  
		   m_RFBXScale.cxStride * m_RFBXScale.cyPixels); 
 
} 
 
RawFrameBufferInfo* CDisplayConfig::GetDesktopFrameBuffer() 
{ 
	if (!m_RFBDesktop.pFramePointer)	// already known? 
	{ 
		// lets get info and map it into Virtual memory 
		DISPCFG_GET_SURFACE_INFO surfinfo; 
 
		// get size info  
		memset(&surfinfo, 0, sizeof (DISPCFG_GET_SURFACE_INFO)); 
		surfinfo.eDisplaySurface = DCFG_DESKTOP; 
 
		int nEscRtn = ExtEscape( m_hdcMarathon, 
						 DRVESC_GET_SURFACEINFO, 
						 sizeof(DISPCFG_GET_SURFACE_INFO), 
						 (LPSTR) &surfinfo, 
						 sizeof(DISPCFG_GET_SURFACE_INFO), 
						 (LPSTR) &surfinfo 
						 ); 
 
		TRACE(L"Desktop FB appears to be at Physical Mem: 0x%08X\n\r", surfinfo.sPhysSurfaceInfo.ulPhysAddress); 
		ASSERT(NULL == m_pBufDesktop); // if m_RFBDesktop.pFrameBuffer was null, pointer to mem should be too 
		m_pBufDesktop = ConvertSurfaceInfoToRawFrameBuffer(surfinfo, m_RFBDesktop); 
	} 
	return &m_RFBDesktop; 
} 
 
RawFrameBufferInfo* CDisplayConfig::GetXScaleFrameBuffer() 
{ 
 
	// Note:  This rountine should simply use the GETRAWFRAMEBUFFER escape fo the XScale display driver 
	//			when it is implemented 
 
	if (!m_RFBXScale.pFramePointer)	// already known? 
	{ 
#define PAGE_SIZE			0x1000 
#define ALIGNMENT_MASK		(PAGE_SIZE-1) 
 
#ifndef GETVFRAMEPHYSICAL 
#define GETVFRAMEPHYSICAL		6144 
#define GETVFRAMELEN			6145 
#endif //GETVFRAMEPHYSICAL 
 
 
		int nEscRtn; 
		PBYTE pVXScaleFB = NULL; 
		PVOID pv; 
		PBYTE pSrc; 
		ULONG ulOffset; 
 
		ASSERT(m_hdcXScale); 
		/* Get XScale Frame Buffer */ 
		nEscRtn = ExtEscape(m_hdcXScale, 
						GETVFRAMEPHYSICAL,  
						0,  
						NULL,  
						sizeof(PBYTE), 
						(LPSTR) &pVXScaleFB); 
		if (nEscRtn < 0)  
		{ 
			TRACE(L"Failed to get XScale Frame Buffer Address!\r\n"); 
			return NULL; 
		} 
		 
		ULONG nVGABufferSize; 
		nEscRtn = ExtEscape(m_hdcXScale, 
						GETVFRAMELEN,  
						0,  
						NULL,  
						sizeof(PBYTE), 
						(LPSTR) &nVGABufferSize); 
		if (nEscRtn < 0)  
		{ 
			TRACE(L"Failed to get XScale Frame Buffer size!\r\n"); 
			return NULL; 
		} 
 
 
		ulOffset = (ULONG)pVXScaleFB & ALIGNMENT_MASK; 
		nVGABufferSize += ulOffset ? PAGE_SIZE : 0; 
 
		pv = VirtualAlloc(0, nVGABufferSize, MEM_RESERVE, PAGE_NOACCESS); 
 
		if (!pv) { 
			TRACE(L"**** Could not allocate view of buffer!!! ****\r\n"); 
			return NULL; 
		} 
		pSrc = pVXScaleFB - ulOffset; 
		///////////////////////////////////// Map virtual address to linear 
		if(!VirtualCopy(pv, pSrc, nVGABufferSize, PAGE_READWRITE))  
		{ 
			VirtualFree(pv, 0, MEM_RELEASE); 
			TRACE(L"Failed to map XScale Frame Buffer to linear space!\r\n"); 
			return NULL; 
		} 
 
		ASSERT(NULL == m_pBufXScale); // if m_RFBXScale.pFrameBuffer was null, pointer to mem should be too 
		m_pBufXScale = (PWORD)((PBYTE)pv + ulOffset); 
 
		// strides of XScale display will match the strides of OS "desktop" display. 
		m_RFBXScale = *GetDesktopFrameBuffer();	// copy desktop info into xscale info and then fixup pointer 
		m_RFBXScale.pFramePointer = (PVOID) ( 
			(LONG)m_RFBXScale.pFramePointer -  
			(LONG)m_pBufDesktop +  
			(LONG)m_pBufXScale);  
 
		// in other words,  
		//		m_RFBXScale.pFramePointer is to m_pBufXScale 
		// as 
		//		m_RFBDesktop.pFramePointer is to m_pBufDesktop 
 
	} 
	return &m_RFBXScale; 
} 
 
 
PWORD CDisplayConfig::ConvertSurfaceInfoToRawFrameBuffer(const DISPCFG_GET_SURFACE_INFO &surfinfo, RawFrameBufferInfo &raw) 
{ 
	// Get frame buffer address */ 
	ULONG ulAddr = surfinfo.sPhysSurfaceInfo.ulPhysAddress; 
	ULONG ulSize = surfinfo.sPhysSurfaceInfo.ulStride * surfinfo.sPhysSurfaceInfo.ulHeight; 
	 
	// Make Physical Memory available to Virtual Memory 
	void* pvMemc = VirtualAlloc(0, ulSize, MEM_RESERVE, PAGE_NOACCESS); 
 
	if (!VirtualCopy(pvMemc, (PVOID)(ulAddr / 256),  
				   ulSize, PAGE_READWRITE | PAGE_PHYSICAL))  
	{ 
		VirtualFree(pvMemc, 0, MEM_RELEASE); 
		TRACE(L"Failed to map Marathon\'s Desktop Frame Buffer to linear space!"); 
		return NULL; 
	} 
 
	raw.wFormat = FORMAT_565; 
	raw.wBPP = (WORD)surfinfo.sPhysSurfaceInfo.ulBpp; 
	// pvMemc = Virtual Address of surface memory 
	switch(surfinfo.sPhysSurfaceInfo.lPhysicalRotation) 
	{ 
	default: 
	case 0: 
		raw.pFramePointer = pvMemc; 
		raw.cxStride = surfinfo.sPhysSurfaceInfo.ulBpp/8; 
		raw.cyStride = surfinfo.sPhysSurfaceInfo.ulStride; 
		raw.cxPixels = surfinfo.sPhysSurfaceInfo.ulWidth; 
		raw.cyPixels = surfinfo.sPhysSurfaceInfo.ulHeight; 
		break; 
	case 90: 
		raw.pFramePointer = (LPBYTE)pvMemc + (surfinfo.sPhysSurfaceInfo.ulHeight * (surfinfo.sPhysSurfaceInfo.ulStride-1)); 
		raw.cxStride = -(int)surfinfo.sPhysSurfaceInfo.ulStride; 
		raw.cyStride = surfinfo.sPhysSurfaceInfo.ulBpp/8; 
		raw.cxPixels = surfinfo.sPhysSurfaceInfo.ulHeight; 
		raw.cyPixels = surfinfo.sPhysSurfaceInfo.ulWidth; 
		break; 
	case 180: 
		raw.pFramePointer = (LPBYTE)pvMemc + (surfinfo.sPhysSurfaceInfo.ulHeight * surfinfo.sPhysSurfaceInfo.ulStride) 
			- (surfinfo.sPhysSurfaceInfo.ulBpp/8); // point to last pixel 
		raw.cxStride = -(int)(surfinfo.sPhysSurfaceInfo.ulBpp/8); 
		raw.cyStride = -(int)surfinfo.sPhysSurfaceInfo.ulStride; 
		raw.cxPixels = surfinfo.sPhysSurfaceInfo.ulWidth; 
		raw.cyPixels = surfinfo.sPhysSurfaceInfo.ulHeight; 
		break; 
	case 270: 
		raw.pFramePointer = (LPBYTE)pvMemc + surfinfo.sPhysSurfaceInfo.ulStride 
			- surfinfo.sPhysSurfaceInfo.ulBpp/8; 
		raw.cxStride = surfinfo.sPhysSurfaceInfo.ulStride; 
		raw.cyStride = -(int)(surfinfo.sPhysSurfaceInfo.ulBpp/8); 
		raw.cxPixels = surfinfo.sPhysSurfaceInfo.ulHeight; 
		raw.cyPixels = surfinfo.sPhysSurfaceInfo.ulWidth; 
		break; 
	} 
 
	return (PWORD)pvMemc; 
}