http://blog.csdn.net/DroidPhone/archive/2010/11/02/5982893.aspx

SurfaceFlinger继承了Thread类,自然也继承了Thread类的threadLoop方法,SurfaceFlinger工作线程的主代码都在threadLoop()方法中。工作线程启动后,基类Thread会循环地调用threadLoop方法,SurfaceFlinger的threadLoop()主要是要完成系统中各个Layer(Surface)进行混合(compose),然后不停地把一帧帧混合好的图像数据传送到显示设备中。

threadLoop的流程

图一 threadLoop流程

1. handleConsoleEvents

handleConsoleEvent目前没有深入了解,貌似只是处理显示设备进入休眠状态或者从休眠中唤醒时,改变SufaceFlinger的状态,然后threadLoop的后续流程会根据相应的状态来决定是否继续给显示设备传送显示数据。

2.handleTransaction

因为Layer的混合是在线程中进行的,而混合的过程中,应用程序或者系统可能会改变Layer的状态,例如屏幕旋转、增加或删除Layer、某个Layer可见或不可见,为了使这些变动不会破坏当前正在进行的混合动作,SurfaceFlinger维护着两个Layer列表:

  • mCurrentState.layersSortedByZ ---- 当前系统最新的Layer列表
  • mDrawingState.layersSortedByZ ---- 本次混合操作使用的Layer列表

handleTransaction就是根据Layer列表的这些状态的变化,计算是否有可见区域内需要更新,并设置状态变量mVisibleRegionsDirty,然后把mCurrentState赋值给mDrawingState,最后释放已经被丢弃(ditch)的Layer

  • 上一次混合过程中,可能应用程序释放了一个Layer,可是mDrawingState正在使用,不能马上销毁,所以要等到本次混合前才能做出销毁的动作。

  • 如果Layer的大小有变化并且可见,Layer的handleTransaction将会重新分配缓冲区,并且冻结SurfaceFlinger后续的混合操作,也就是屏幕的内容本次将不会刷新,直到下一个循环的handlePageFlip阶段才解除冻结。

3. handlePageFlip

该阶段会遍历各个Layer,在每个Layer中,取得并锁住该Layer的frontBuffer,然后利用frontBuffer中的图像数据生成该Layer的2D贴图(Texture),并且计算更新区域,为后续的混合操作做准备。

图二 handlePageFlip处理流程

Layer的lockPageFlip()首先通过SharedBufferServer类的成员变量lcblk,调用retireAndLock取得该Layer当前可用的frontBuffer,然后通过reloadTexture方法生成openGL ES的纹理贴图,最后通过unlockPageFlip完成更新区域的Layer坐标到屏幕坐标的变换。

handleRepaint

handleRepaint真正实现Layer混合的阶段,下图是handleRepaint的处理流程:

图三 handleRepaint 的处理流程

handleRepaint首先重置了openGL的观察矩阵,然后遍历mDrawingState.layersSortedByZ中的Layer列表,调用每个Layer的onDraw方法,在onDraw方法中,会调用drawWithOpenGL()方法,将在handlePageFlip阶段生成的贴图混合到OpenGL的主表面,最后handleRepaint把需要刷新的区域清除。

unlockClients

unlockClients只是遍历各个Layer并调用各个Layer的finishPageFlip方法。finishPageFlip会进一步调用SharedBufferServer的unlock()方法:(关于SharedBufferSever,请参考本人以下博文的SharedClient 和 SharedBufferStack一节)

view plain copy to clipboard print ?
  1. voidLayer::finishPageFlip()
  2. {
  3. status_terr=lcblk->unlock(mFrontBufferIndex);
  4. LOGE_IF(err!=NO_ERROR,
  5. "layer%p,buffer=%dwasn'tlocked!",
  6. this,mFrontBufferIndex);
  7. }

void Layer::finishPageFlip() { status_t err = lcblk->unlock( mFrontBufferIndex ); LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, mFrontBufferIndex); }

lcblk->unlock( mFrontBufferIndex )会把Layer的frontBuffer解除锁定。

postFramebuffer

进入postFramebuffer阶段,OpenGL主表面已经准备好了混合完成的图像数据,postFramebuffer只是简单地调用hw.flip(),hw.flip()进一步调用了eglSwapBuffers完成主表面的切换,这样屏幕上的图像就会更新为新的数据。

更多相关文章

  1. android Button实现点击事件的三种方法
  2. FileProvider 调用系统相机拍照 出现on a null object reference
  3. Android开发工具GenyMotion安装和使用方法
  4. 关于 android 的JNI的java 调用 C和 C 调用JAVA(2)
  5. Android如何在初始化的时候获取加载的布局的宽高
  6. android-在代码中实现按下Home键的效果
  7. android scrollview嵌套scrollview,gridview,listview的方法和深
  8. 【Android源码】Intent 源码分析
  9. Android视图加载流程(5)之View的详细绘制流程Layout

随机推荐

  1. android 中,关于线程安全退出的问题(from s
  2. Android(安卓)— 创建和修改 Fragment 的
  3. android:visibility
  4. android之sax解析xml文件
  5. android中调用相册里面的图片并返回
  6. android中的一个属性动画,可以显示更多的
  7. TP 支付订单、购物车页面数据、购物车(九
  8. localStorage实现本地存储读取CSS样式
  9. localStorage实现本地存储读取CSS样式
  10. 访问器属性,类与构造器函数,document.query