android surface管理

来源:互联网 发布:linux配置tomcat 编辑:程序博客网 时间:2024/06/03 15:31

当窗口的内容或者状态发生变化时,Surface Flinger就会在监听线程中监听到相关的事件,并进行处理。首先判断事件是不是控制台信号,如果是控制台信号,就调用handleConsoleEvents()方法进行控制台信号的处理,获取渲染的区域;当交易处理完成时,Surface Flinger会在handleTransaction()方法中遍历Z-order上的Layer,移去已经被销毁的Layer;接下来Surface Flinger会遍历LayerVector,计算每个Layer的可视区域,如果需要重绘,在handleRepaint()方法中会进行Layer组合,当组合完成后,会发送消息compositionComplete()通知硬件Layer组合已经完成,然后进行Surface的渲染。

关于Surface,还有一个十分重要的概念就是layer_state_t,根据窗口状态的变化,Layer处于不同的状态。layer_state_t的值包括ePositionChanged、eLayerChanged、eSizeChanged、eAlphaChanged、eMatrixChanged、eTransparentRegionChanged、eVisibilityChanged等。当发生eLayerChanged变化时,说明缓冲需要切换。另外,不论layer_state_t值发生了何种变化,都需要重新遍历Layer,进行相应的重绘。
一般而言,屏幕的渲染需要重绘Surface的所有像素,但是出于提高效率和速率的需要,在现代的设计上,会通过分析只重绘发生变化的区域。这部分的内容主要位于framebuffer.cpp的fb_post()函数中。在“LayerBuffer”和“LayerDim”模式的Layer中也有采用。
在Surface上层,主要由窗口管理器来控制着窗口的变化。

当Windows Manager要创建Surface时,首先会创建一个Java Surface对象,Java Surface对象通过Java JNI会获得一个SurfaceComposerClient句柄,然后通过SurfaceComposerClient向Surface Flinger请求创建一个原生层的C++ Surface对象和一个SurfaceControl对象。在Surface Flinger中,根据标志位(PUSH_BUFFERS、FX_SURFACE_NORMAL、FX_SURFACE_BLUR、FX_SURFACE_DIM)的不同,调用相应的方法创建相应类型的Layer。每个Surface都有一个唯一的标识符SurfaceID。
为了执行窗口的操作,需要调用Surface.openTransaction()方法打开交易(Transaction)。在原生层,SurfaceFlinger会调用openGlobalTransaction()方法增加交易记数(mTransactionCount),并将交易ID保存在gActiveConnections向量中。
Windows Manager通过调用Surface. setPosition()方法可以设置Surface的位置,当SurfaceComposerClient收到设置Surface位置的请求时,会将layer_state_t状态设为ISurfaceComposer::ePositionChanged,SurfaceFlinger在收到位置变化的消息后,会在其监听线程中进行处理。
Windows Manager通过调用Surface. setLayer ()方法可以设置Surface的Layer,当SurfaceComposerClient收到设置Surface的Layer请求时,会将layer_state_t状态设为ISurfaceComposer::eLayerChanged,SurfaceFlinger在收到Layer变化的消息后,会在其监听线程中进行处理。

 如果希望隐藏已经创建的Surface,需要调用Surface.hide()来调用原生层的SurfaceComposerClient::hide()方法,SurfaceComposerClient会将其标志位和掩码均设为ISurfaceComposer::eLayerHidden,并向SurfaceFlinger发送ISurfaceComposer:: eVisibility Changed消息。
当交易结束时,Windows Manager需要通过Surface.closeTransaction()方法通知原生层交易结束。
需要说明的是,交易过程中的Java Surface对原生层C++ Surface的调用,是通过SurfaceControl对象来进行的。
实际应用中要注意,如果通过activity创建的surface传递给service使用,然后在service中使用surface创建egl窗口,在activity状态变化时,surface会有变更,此时service中egl相关初始化或opengl描画动作会失败。由于有异步存在,此流程不容易控制。建议监视egl相关error内容,发生类似bad_native_window的err时停止描画动作,否则会导致assert。

0 0
原创粉丝点击