完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
二.技术方案的具体实现
1.硬件层面的实现原理 RK3188 PX3 RK3288 RK3399 的 SOC 内部,都有集成两个 LCDC 控制器,因此这就给双 屏异显功能的实现提供了基础。那么软件上的实现就是通过开辟两块不同的 buffer,对应外部的 物理屏幕。然后每块 buffer,通过不同 LCDC 送给对应的屏幕,即实现了双屏异显的功能。所以 这也是为什么必须有两块 LCDC 的 SOC 才能去做双屏异显功能的原因。 我司采用的rk3288平台就有2个LCD控制器,可以外接两个屏幕。我司采用的方案是,LCDC0接LVDS接口的屏幕(18.5寸的主屏),LCDC1接EDP接口的屏幕(10.1寸的副屏)。硬件逻辑图如下所示: 2.底层软件层面的实现原理 默认情况下,我司rk3288芯片上跑的Android 6.0系统只能通过LCD0控制器输出图像给一个屏幕显示。要支持同时通过LCDC0和LCDC1输出图像给两个屏幕显示,必须修改代码。经过分析软件实现的原理图如下: 下面是对上面原理图的解析: a.保证两个屏幕单独作为主屏的时候都可以正常显示,这样子保证了两个屏幕的屏参都是正确的,而且两个屏幕的物理连接都正常。 开始调试两个屏幕同时显示 b.双屏显示控制部分的实现:默认情况下rk_screen.c驱动代码里只会去解析dts里主屏的屏参,在里面加入代码使得根据id同时去解析副屏的屏参。然后LCDC0的驱动rk32_lvds.c以及LCDC1的驱动rk32_dp.c同时去获取屏幕的相关参数(读取刚才rk_screen.c里配置的相关结构体)。这样子两个屏幕的LCD控制器部分的驱动都完善了。 c.双屏显示数据部分的实现:已知android系统抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。FrameBuffer机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过FrameBuffer的读写直接对显存进行操作。用户可以将FrameBuffer看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节,这些都是由FrameBuffer设备驱动来完成的。 rk系统里面framebuffer的驱动为rk_fb.c。主屏为/dev/graphics/fb0,副屏为/dev/graphics/fb4,上层通过打开这两个节点返回文件描述符,通过文件描述符写入两个屏幕的数据,然后DMA,把缓冲区里的数据传给屏幕。默认情况下rk_fb.c只会去分配一块缓冲区给主屏用,需要修改代码,根据副屏的屏参分配缓冲区给副屏用,大小为长宽每个像素的位数。 3.在底层实现双屏同显的基础上,APP中去实现双屏异显 通过前面底层的修改,已经实现了双屏可以同时输出相同的内容。为了支持两个屏幕实现不同的内容,可以在APP中操作。 Android 的标准实现是使用 API Presentation 来实现异显的功能。 Presentation 是扩展自 dialog. Presentation 是 Android 针对双屏异显所开发的一个类。它可以做到一个 APK 里面,通过给Presentation 单独进行 view 的布局,来实现同一个 APK 在主屏和副屏上面显示不同的 view,来达到异显的效果。它的工作原理是通过调用 DisplayManagerService 的 getDisplays 方法来获取第二个显示设备。将第二个显示设备作为参数传给 Presentation,然后在 Presentation 里面实现自己的 UI内容,最终调用 Presentation 的 show 方法来将 UI 内容显示在第二个显示设备上面。下面是我写的一个简单的 Demo。 public class MainActivity extends Activity { private DemoPresentation mPresentation; private Display[] displays; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DisplayManager mDisplayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE); displays = mDisplayManager.getDisplays(); mPresentation = new DemoPresentation(MainActivity.this, displays[1]); Button Button1=(Button) findViewById(R.id.button1); Button1.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { //这里进行副屏显示的调用 mPresentation.show(); } }); } public class DemoPresentation extends Presentation { //private PresentationContents mContents; public DemoPresentation(Context outerContext, Display display) { super(outerContext, display); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Resources r=getContext().getResources();//根据 prsentation 的上下文获取到资源文件 setContentView(R.layout.main2); Button Button2=(Button) findViewById(R.id.button2); videoView1 = (VideoView) findViewById(R.id.videoView1); if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { File file = Environment.getExternalStorageDirectory(); File videoFile = new File(file, “testvideo.mp4”); if (videoFile.exists()) { uri = Uri.fromFile(videoFile); videoView1.setVideoURI(uri); VideoView1.setMediaController(controller); videoView1.requestFocus(); playVideo(); } } } 这个 Demo 最终实现的是同一个 APK,主屏显示一些如 button 等的 view,然后副屏可以显示一个SurfaceView,及播放一个视频。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
【飞凌嵌入式OK3576-C开发板体验】SSH远程登录网络配置及CAN通讯
197 浏览 0 评论
2057 浏览 3 评论
rk1126实现BT601输入,输入不带IIC接口的驱动程序
3829 浏览 0 评论
2340 浏览 1 评论
3577 浏览 3 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-9-30 16:23 , Processed in 0.565578 second(s), Total 68, Slave 54 queries .
Powered by 电子发烧友网
© 2015 www.ws-dc.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号