Android Graphics 显示体系 - VirtualDisplay的初印象 - 简单示例 ...

打印 上一主题 下一主题

主题 968|帖子 968|积分 2904

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
开始预备这篇文章时巴黎奥运会赛场上激战正酣,写完时奥运已落下帷幕,期间也看了许多出色的赛事直播,拼搏与汗水书写的传奇无不激励着平凡岗位上的我们。每一枚奖牌的背后,都凝结着运动员数不尽的汗水付出与坚持不懈,学习Android Graphics显示体系的知识,也需要我们长久的坚持、不停地探索实践。一点一滴地积累,一万小时天才定律,相信你终将赢得属于本身的金牌。

媒介


在许多场景中都会用到Android 虚拟屏幕VirtualDisplay,比如常见的屏幕录制、WifiDisplay(Miracast)。固然,本系列的目的还是盼望给大家解说底层Graphics体系中虚拟屏幕的一些儿运作逻辑,至于上层框架的WindowManagerService/DisplayManagerService等无非就是在框架层增加了更丰富的控制接口逻辑,但其本质还是在SurfaceFlinger、HWC等较低层面完成虚拟屏幕的焦点功能。
还是老样子,抛开WMS等复杂逻辑,我们从简单的demo开始,来了解VirtualDisplay的使用及运作逻辑。

Android VirtualDisplay示例


基于Android 14平台开辟了一个极简的创建虚拟屏幕的示例,代码至文末下载获取
使用方法


  • 下载代码放到android源码目录下;
  • 执行mm编译得到可执行档 VirtualDisplayDemo;
  • push到测试环境中;
    adb push VirtualDisplayDemo /system/bin/
  • 运行步伐;
    1. adb shell VirtualDisplayDemo 
    复制代码
结果展示
dumpsys SurfaceFlinger看看虚拟屏幕的信息
  1. Display 11529215050109536902 (<strong>virtual, "Super-VirtualDisplay"</strong>)
  2.    Composition Display State:
  3.    isEnabled=true isSecure=false usesDeviceComposition=false 
  4.    usesClientComposition=true flipClientTarget=false reusedClientComposition=false 
  5.    layerFilter={<strong>layerStack</strong><strong>=</strong><strong>99</strong> toInternalDisplay=false }
  6.    transform (ROT_0) (SCALE )
  7.     0.5000  0.0000  0.0000
  8.     0.0000  0.5000  0.0000
  9.     0.0000  0.0000  1.0000
  10. <strong>   layerStackSpace</strong><strong>=ProjectionSpace{bounds=Rect(0, 0, 1920, 1080), content=Rect(0, 0, 1920, 1080), orientation=ROTATION_0} 
  11.    </strong><strong>framebufferSpace</strong><strong>=ProjectionSpace{bounds=Rect(0, 0, 960, 540), content=Rect(0, 0, 960, 540), orientation=ROTATION_0} 
  12.    </strong><strong>orientedDisplaySpace</strong><strong>=ProjectionSpace{bounds=Rect(0, 0, 960, 540), content=Rect(0, 0, 960, 540), orientation=ROTATION_0} 
  13.    </strong><strong>displaySpace=ProjectionSpace</strong><strong>{bounds=Rect(0, 0, 960, 540), content=Rect(0, 0, 960, 540), orientation=ROTATION_0} </strong>
  14.    needsFiltering=true 
  15.    colorMode=NATIVE (0) renderIntent=COLORIMETRIC (0) dataspace=UNKNOWN (0) targetDataspace=UNKNOWN (0) 
  16.    colorTransformMatrix=[[1.000,0.000,0.000,0.000][0.000,1.000,0.000,0.000][0.000,0.000,1.000,0.000][0.000,0.000,0.000,1.000]] 
  17.    displayBrightnessNits=-1.000000 sdrWhitePointNits=-1.000000 clientTargetBrightness=1.000000 displayBrightness=nullopt 
  18.    compositionStrategyPredictionState=DISABLED 
  19.    treat170mAsSrgb=false 
  20.    Composition Display Color State:
  21.    HWC Support: wideColorGamut=false hdr10plus=false hdr10=false hlg=false dv=false metadata=0 
  22.    Composition RenderSurface State:
  23.    size=[960 540] ANativeWindow=0x71ab9e8b4010 (format 1) 
  24. <strong>   0 Layers</strong>
复制代码
可以看到几个主要信息:


  • 虚拟屏幕的名字是我们设置的:Super-VirtualDisplay;
  • 虚拟屏幕的 layerStack是我们设置的:99;
  • layerStackSpace/framebufferSpace/orientedDisplaySpace/displaySpace 也是我们配置的;
  • 此时还没有任何图层显示到这个虚拟屏幕上 0 Layers;
虚拟屏幕显示画面
现在,我们往这块虚拟屏幕上显示点内容,看看结果
使用我们前面提供的demo: MultiDisplayDemoPro
Android Graphics 多屏同显/异显 - C++示例步伐(升级版)
执行命令,-d 99 指定显示到虚拟屏幕
  1. adb shell MultiDisplayDemoPro -f /sdcard/720P25FPS.mp4 <strong>-d </strong><strong>99</strong>
复制代码


此时,再去观察dumpsys SurfaceFlinger的信息,虚拟屏幕下就有一个layer了
  1. Display 11529215050109536902 (<strong>virtual, "Super-VirtualDisplay"</strong>)
  2.    Composition Display State:
  3.    isEnabled=true isSecure=false usesDeviceComposition=false 
  4.    。。。。。
  5.  <strong>  1 Layers</strong>
  6.   - Output Layer 0x71ac6e779b10(<strong>MultiDisplayDemo#94</strong>)
复制代码
虚拟屏幕没有物理实体,但仍需要一个承载合成后数据的“载体”,我们demo中就是在主屏幕上创建了一个 Surface 来吸收虚拟屏幕的数据,这样便于我们观察。
显示在左上角 pos=(100, 100) 的位置
  1. + Layer (<strong>VirtualDisplay-Surface#90</strong>) uid=0
  2.   Region TransparentRegion (this=0 count=0)
  3.   Region VisibleRegion (this=0 count=0)
  4.   Region SurfaceDamageRegion (this=0 count=0)
  5.       layerStack=   0, z=2147483647, <strong>pos=(100,100)</strong>, size=(   0,   0), crop=[  0,   0,  -1,  -1], cornerRadius=0.000000, isProtected=0, isTrustedOverlay=0, isOpaque=0, invalidate=1, dataspace=BT709 sRGB Full range, defaultPixelFormat=Unknown/None, backgroundBlurRadius=0, color=(-1.000,-1.000,-1.000,1.000), flags=0x00000000, tr=[0.00, 0.00][0.00, 0.00]
  6.       parent=none
  7.       zOrderRelativeOf=none
  8.       activeBuffer=[   0x   0:   0,Unknown/None], tr=[0.00, 0.00][0.00, 0.00] queued-frames=0 metadata={9:4bytes}, cornerRadiusCrop=[0.00, 0.00, 0.00, 0.00],  shadowRadius=0.000, 
  9. + Layer (<strong>bbq-wrapper#91</strong>) uid=0
  10.   Region TransparentRegion (this=0 count=0)
  11.   Region VisibleRegion (this=0 count=1)
  12.     [100, 100, 1060, 640]
  13.   Region SurfaceDamageRegion (this=0 count=0)
  14.       layerStack=   0, z=        0, <strong>pos=(100,100)</strong>, size=(   0,   0), crop=[  0,   0,  -1,  -1], cornerRadius=0.000000, isProtected=0, isTrustedOverlay=0, isOpaque=0, invalidate=0, dataspace=BT709 sRGB Full range, defaultPixelFormat=RGBA_8888, backgroundBlurRadius=0, color=(-1.000,-1.000,-1.000,1.000), flags=0x00000100, tr=[0.00, 0.00][0.00, 0.00]
  15.       parent=VirtualDisplay-Surface#90
  16.       zOrderRelativeOf=none
  17.       activeBuffer=[ <strong>960x 540</strong>:2816,RGBA_8888], tr=[0.00, 0.00][0.00, 0.00] queued-frames=0 metadata={dequeueTime:1902680300269, 9:4bytes}, cornerRadiusCrop=[0.00, 0.00, 0.00, 0.00],  shadowRadius=0.000, 
复制代码
固然也可以选择别的“载体”,比如


  • 把虚拟屏幕合成后的数据放入编码器encoder再写入MP4文件,那就是screenrecord 的功能了;
  • 把虚拟屏幕合成后的数据放入编码器encoder再打包按照网络协议(RTSP...)发送出去,那就是 WifiDisplay(Miracast)的功能了;

阅读原文,下载源码

Android Graphics 显示体系 - VirtualDisplay的初印象 - 简单示例


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

前进之路

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表