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;
}