[问题求助] 进来讨论一下WINCE如何动态改变分辨率?
RT,最近小弟我在做WINCE(WINCE6)下动态改变分辨率的功能,起源于本公司的WINCE6平台支持HDMI输出,当HDMI以不同分辨率(1280*720,1920*1080,720*480。。。)输出时,希望wince能动态的改变分辨率,以使UI层能够在HDMI TV上全屏显示。 ' B9 |# m$ ~2 R0 V: C 工作了一天,添加了一个驱动,在应用层使用DeviceIoControl要求底层驱动根据新的分辨率对LCD控制器重新配置,这段代码验证没有问题。但是结果是花屏,我在想修改完LCD控制器的配置后,如何通知WINCE内核(或者说GDI),要求其重载重绘?如果能让WINCE重绘重载显示驱动,那么估计我就能成功了。。。。请问该如何操作呀?不知道哪位哥们做过类似的开发?一起分享一下经验吧。。。。。 |
==================================================================================
动态改变分辨率在CE6上面是没问题的(CE5不行),但是不是让应用层调用IOControl,应用层应该调用ChangeDisplaySettingsEx,然后由display driver去处理。
display driver那边要报多个分辨率,然后在GPE::SetMode处理一下。
SCODE ANYKADISP::SetMode (INT modeId, HPALETTE *palette)
{
RETAILMSG(HAL_ZONE_INIT, (TEXT("++ANYKADISP::SetMode/r/n")));
if (modeId != 0)
{
RETAILMSG(HAL_ZONE_INIT, (TEXT("ANYKADISP::SetMode Want mode %d, only have mode 0/r/n"),modeId));
return E_INVALIDARG;
}
if (palette)
{
*palette = EngCreatePalette (PAL_BITFIELDS, 0, NULL, gBitMasks[0], gBitMasks[1], gBitMasks[2]);
}
m_dwPhysicalModeID = m_pMode->modeId;
m_CursorHotspot.x = 0;
m_CursorHotspot.y = 0;
RETAILMSG(HAL_ZONE_INIT, (TEXT("--ANYKADISP::SetMode/r/n")));
return S_OK;
}
==================================================================================
我见过有做成动态设置分辨率的,不过设置完以后,都要重新启动一下才可以,不知道不重新启动有没有办法做到。 |
==================================================================================
如果你直接用IOCTL,花屏基本上是免不了的,因为你没有通知系统,而系统的gwes负责了很大一块UI和消息的处理。
==================================================================================
如果你是通过ChangeDisplaySettingsEx通知驱动的,那么系统就会知道,它会帮你调整界面. 2 I/ d4 ~1 P s. w2 H1 O
我记得怎么改不繁的,还是直接用ChangeDisplaySettingsEx吧,大概就做这么几步:
, A6 Z" L8 _9 w- I
SetMode运行前系统应该已经把当前primary surface删除了,你需要在SetMode中重新分配primary surface。
==================================================================================
貌似飞凌的网站上看到过,不过俺不懂,建议楼主去咨询一下。
==================================================================================
Display驱动里面,GetModeInfo;NumModes等函数需要告诉OS有两种显示模式,例如一个是320*240 16bpp,另一个是320*240 24bpp。然后调用ChangeDisplaySettingsEx,上层应该就会调用驱动的SetMode来切换显示模式。完全不用重新启动。可以参考微软的例子wince500/public/common/oak/csp/x86/geode/gxvideo/base/Misc.cpp
http://topic.csdn.net/u/20090407/16/878b6cb7-32b4-428e-ab37-0617301bdccd.html
==================================================================================
你说的是设备重起么?如果设备重起叫什么动态设置分辨率啊
不过display driver里面是要重新reset一下的
==================================================================================
ruritanian,
能否提供实现GetModeInfo,NumModes和SetMode这三个函数的参考代码。我在我的display驱动中找到了这三个函数,但是实现挺简单的:
SCODE
TCCDISP::GetModeInfo(GPEMode *mode, int modeNo)
{
//RETAILMSG(TC_LOG_LEVEL(TC_DEBUG), (TEXT("[DISPLAY ] TCCDISP::GetModeInfo()/n/r")));
if (modeNo != 0)
{
RETAILMSG(TC_LOG_LEVEL(TC_ERROR), (TEXT("[DISPDRV:ERR] GetModeInfo() : modeNo = %d, Driver Support Only Mode 0/n/r"), modeNo));
return E_INVALIDARG;
}
*mode = *m_pMode;
return S_OK;
}
int
TCCDISP::NumModes()
{
RETAILMSG(TC_LOG_LEVEL(TC_DEBUG), (TEXT("[DISPLAY ] TCCDISP::NumModes()/n/r")));
return 1;
}
SCODE
TCCDISP::SetMode (INT modeId, HPALETTE *palette)
{
SCODE scRet = S_OK;
RETAILMSG(TC_LOG_LEVEL(TC_LOG), (TEXT("[DISPLAY ] ++TCCDISP::SetMode(%d)/n/r"), modeId));
if (modeId == 0)
{
m_dwPhysicalModeID = m_pMode->modeId;
// Create Palette
if (palette)
{
*palette = EngCreatePalette(PAL_BITFIELDS, 0, NULL, gBitMasks[0], gBitMasks[1], gBitMasks[2]);
}
//Allocate Primary Surface
if (NULL == m_pPrimarySurface)
{
if (FAILED(AllocSurface((DDGPESurf **)&m_pPrimarySurface,
m_nScreenWidthSave, m_nScreenHeightSave,
m_pMode->format, m_pModeEx->ePixelFormat,
GPE_REQUIRE_VIDEO_MEMORY)))
{
RETAILMSG(TC_LOG_LEVEL(TC_ERROR), (TEXT("[DISPLAY ] SetMode() : m_pPrimarySurface AllocSurface() Fail/n/r")));
scRet = E_INVALIDARG;
}
else
{
m_pVisibleSurface = (TCCDISPSurf*)m_pPrimarySurface;
}
}
m_pPrimarySurface->SetRotation(m_nScreenWidth, m_nScreenHeight, m_iRotate);
}
else
{
RETAILMSG(TC_LOG_LEVEL(TC_ERROR), (TEXT("[DISPLAY ] SetMode() : modeId = %d, Driver Support Only Mode 0/n/r"), modeId));
scRet = E_INVALIDARG;
}
#ifdef _USING_HW_ACCELETE_
//reserved for H/W Accelerate Dump Memory
pHWTempHeap = m_pVideoMemoryHeap->Alloc(800*480*4);
#endif
RETAILMSG(TC_LOG_LEVEL(TC_LOG), (TEXT("[DISPLAY ] --TCCDISP::SetMode()/n/r")));
return scRet;
}
=================================================================================
你先把GetModeInfo和NumModes按照我说的实现了,然后再调一下SetMode,看上去你的代码里SetMode已经分配Primary surface了。SetMode里面的代码各家都不一样,需要调试一下。
=================================================================================
哪个API会调用SetMode?还有加入我准备好几套分辨率的参数,应该在哪里初始化呢?
http://www.intelligraphics.com/introduction-wince-driver-development
=================================================================================
ruritanian,
能给我讲讲display驱动中实现DDGPE继承类的各个成员函数或者GDI函数的调用流程吧?
=================================================================================
这周非常爽,我已经在TCC8900 WINCE平台做出了动态改变WINCE分辨率。如同ruritanian群友所说的,
1.需要DISP驱动中准备好自己需要的分辨率模式,比如说800*480和1280*720两种模式。放在一个GPEModeEx m_ModeInfoEx[2];数组中 其中m_ModeInfoEx中每个元素的modeId为0和1,以此类推
2.然后可以在TCCDISP::TCCDISP()构造函数中适当对m_ModeInfoEx进行初始化;
3.TCCDISP::NumModes()中必须返回2,也就是数组m_ModeInfoEx的元素大小;TCCDISP::GetModeInfo(GPEMode *mode, int modeNo)函数根据modeNo来判断是否支持;TCCDISP::SetMode就是根据modeId要求来新建m_pPrimarySurface,然后分配给m_pVisibleSurface;
4.应用程序部分我是用以下代码调用的:
case ID_RESOLUTION_1280:
MessageBox(hWnd, TEXT("ID_RESOLUTION_1280"),TEXT("Resolution"),MB_OK);
while (TRUE == EnumDisplaySettings(NULL, maxModeIndex, &DevMode))
/*检索显示模式列表,取出该结构体的地址赋给&DevMode,即&DevMode指向等待切换的显示模式
该结构体定义时,需要对其2个属性进行设置如下:
devmode.dmSize=sizeof(DEVMODE);
devmode.dmDriverExtra=0;
*/
{
maxModeIndex++;
if((DevMode.dmPelsWidth == 1280)&&(DevMode.dmPelsHeight == 720)) //确认显示模式是否正确
{
SaveLCDStatus( 1280,720);//修改注册表键值,存入将要切换的分辨率
Ret = ChangeDisplaySettingsEx(NULL,&DevMode,NULL,CDS_RESET,NULL) ;//进行切换
if(Ret != DISP_CHANGE_SUCCESSFUL) //判断是否切换成功
{
printf("Mode %d: Display mode resolution test failed.", maxModeIndex));
}else{
printf("ChangeDisplaySettingsEx dwRet = %d /r/n", Ret);
break;
}
}
}
break;
case ID_RESOLUTION_480:
while (TRUE == EnumDisplaySettings(NULL, maxModeIndex, &DevMode))
{
maxModeIndex++;
if((DevMode.dmPelsWidth == 800)&&(DevMode.dmPelsHeight == 480))
{
SaveLCDStatus( 800,480);
Ret = ChangeDisplaySettingsEx(NULL,&DevMode,NULL,CDS_RESET,NULL) ;
if(Ret != DISP_CHANGE_SUCCESSFUL)
{
printf("Mode %d: Display mode resolution test failed."), maxModeIndex);
}else{
printf("ChangeDisplaySettingsEx dwRet = %d /r/n", Ret);
break;
}
}
}
break;
================================================================================
http://topic.csdn.net/u/20091207/19/29c03a48-7616-4e1a-bbbe-b45a5e887c2d.html
仔细阅读安凯BSP与显示Mode相关的代码,位于anykaDisp.cpp