深入Android系统Android图形显示系统-1-显示原理与Surface
Posted 智恩架构师
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入Android系统Android图形显示系统-1-显示原理与Surface相关的知识,希望对你有一定的参考价值。
-
Window Positioning
中的WindowManager
主要是用来控制Window
对象 -
Window
对象是用来存放View
对象的容器,每个Window
对象都会关联Surface
对象 -
WindowManager
监视Window
对象的生命周期、输入和焦点事件、屏幕方向、转换、动画、位置、变换、z顺序等 -
然后将所有
Window
元数据发送给SurfaceFlinger
,SurfaceFlinger
利用这些元数据把自己管理的所有Surface
组合成layer
-
然后交给
Hardware Composer
做进一步处理 -
HAL
层中的Hardware Composer(HWC)
会根据当前硬件来进一步进行缓冲区的组合,它的具体实现依赖于特定的显示设备 -
官网关于
HWC
的数据流如下:
SurfaceFlinger
作为client
向HWC
提供一个完整的layer
列表,然后询问HWC
计划如何处理HWC
会将这些layer
标记为client合成
或者device合成
并告知SurfaceFlinger
SurfaceFlinger
将处理标记为client合成
的layer
,然后通过BufferQueue
传递给HWC
- 余下的
layer
由HWC
自行处理
网上一篇很有趣的渲染总结(文中有些错误,但瑕不掩瑜):Android渲染原理
VSYNC信号
前面提到Linux
使用Framebuffer
来用作显示输出。但是,如果在屏幕更新到一半时,用户进程更新了Framebuffer
中的数据,将导致屏幕上画面的上半部分是前一帧的画面,下半部分变成了新的画面。当然这种异常会在下次刷新时纠正过来,但是在用户感知上画面会出现闪烁感
- 针对这种情况,早期的解决方法是使用
双缓冲机制
,双缓冲就是提供两块Framebuffer
,一块用于显示,另一块用于数据更新,数据准备好后,通过ioctl
操作告诉显示设备切换用于显示的Framebuffer
,这样图像就能快速的显示出来了 - 但是双缓冲并没有完全解决问题,虽然双缓冲切换的速度很快,但是如果切换的时间点不对,在画面更新一半的时候进行切换,还是会出现单缓冲区遇到的闪烁问题
- 当然,可以在底层进行控制,当收到切换请求后内部并不马上执行,而是等到刷新完成后再切换,这样可以完全避免画面重叠的问题
- 但是,这样做会带来新的问题,如果
ioctl
操作完成后缓冲区没有切换,应用就不能确定何时可以再使用缓存区,只能通过ioctl
不停地查询缓冲区状态,直到切换完成。这种CPU
主动查询的方式很低效
为此android
让底层固定地发送信号给用户进程,通知进程切换的时机,这样就避免了用户进程主动查询的操作。而这个信号就是VSYNC
信号
官方传送门:
VSYNC
官方描述如下:VSYNC
信号用来同步整个显示流程(Display Pipeline)
。显示流程
包括app
渲染、SurfaceFlinger
合成、HWC
(硬件渲染)组成
(这部分感觉原文更容易理解)VSYNC synchronizes the time apps wake up to start rendering, the time SurfaceFlinger wakes up to composite the screen, and the display refresh cycle.
VSYNC
信号应该由显示驱动产生,这样才能达到最佳效果。但是Android
为了能运行在不支持VSYNC
机制的设备上,也提供了用软件来模拟产生VSYNC
信号的手段
官网描述:通过
HWC
来产生VSYNC
信号,并通过接口回调将事件进行发送(主要是SurfaceFlinger
进行事件接收)
基础知识铺垫完成,我们先来看看Surface
Surface
官网对
Surface
的描述是:A surface is an interface for a producer to exchange buffers with a consumer.
上面描述的是一种生产者-消费者
的模式,而Surface
充当了中间衔接的角色。
以Activity
中UI
显示为例:
-
生产者
的任务就是把图形绘制在Surface
对象上 -
比较出名的生产者就是
SurfaceView
组件了 -
SurfaceFlinger
作为消费者
会把所有Surface
对应的图像层混合在一起 -
最后
消费者
将其输出到FrameBuffer
中,这样在屏幕上就看到最后合成的图像了
下面我们从Java层
开始分析Surface
应用中Surface
的创建过程
应用开发中很少直接使用Surface
,因为每个Activity
中都已经创建好了各自的Surface
对象,通常只有一些特殊的应用才需要在Activity
之外再去创建Surface
,例如相机、视频播放应用。
不过,通常这些应用也是通过创建SurfaceView
来使用Surface
需要注意的是,在应用中不能直接去创建一个可用的Surface
对象(也可以说直接创建出的对象没什么实际用途),因为这样创建出的Surface
对象和SurfaceFlinger
之间没有任何关联。
该如何创见一个可用的Surface
对象呢?
我们看下Surface
类的定义:
public class Surface implements Parcelable
long mNativeObject;
// 一个无参构造,空实现
public Surface()
public Surface(SurfaceTexture surfaceTexture)
if (surfaceTexture == null)
throw new IllegalArgumentException(“surfaceTexture must not be null”);
mIsSingleBuffered = surfaceTexture.isSingleBuffered();
synchronized (mLock)
mName = surfaceTexture.toString();
setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
Surface
类对外有两个构造方法:
-
一个是无参构造,实现也是空的
-
注释中说这个主要是给
readFromParcel()
反序列化用的 -
那我们看下
readFromParcel()
方法
public void readFromParcel(Parcel source)
if (source == null)
throw new IllegalArgumentException(“source must not be null”);
synchronized (mLock)
mName = source.readString();
mIsSingleBuffered = source.readInt() != 0;
setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
-
另一个需要传递
SurfaceTexture
对象作为参数 -
这就复杂了,还要准备一个
SurfaceTexture
对象
聪明的我们会发现,readFromParcel()
和new Surface(SurfaceTexture surfaceTexture)
都会执行一个setNativeObjectLocked()
方法,我们看下方法实现:
private void setNativeObjectLocked(long ptr)
if (mNativeObject != ptr)
…
mNativeObject = ptr;
…
setNativeObjectLocked()
方法很简单,只是更新了mNativeObject
变量的数值,重点就是参数了:
setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
这两个setNativeObjectLocked()
方法的调用从参数的命名来看是针对不同数据来源的处理。
看来要看下native
的实现了,以nativeReadFromParcel()
为例来看下:
static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
jlong nativeObject, jobject parcelObj)
Parcel* parcel = parcelForJavaObject(env, parcelObj);
…
android::view::Surface surfaceShim;
// 解析 Parcel 数据,并填充到 native层 的 Surface对象 surfaceShim
surfaceShim.readFromParcel(parcel, /nameAlreadyRead/true);
// 将传入的指针转换为 native层 的 Surface对象 self
sp self(reinterpret_cast<Surface *>(nativeObject));
// 比对 surfaceShim 和 self 中的 Binder 对象 IGraphicBufferProducer
if (self != nullptr
&& (IInterface::asBinder(self->getIGraphicBufferProducer()) ==
IInterface::asBinder(surfaceShim.graphicBufferProducer)))
// 判断是同一个 IGraphicBufferProducer ,直接返回当前指针
return jlong(self.get());
sp sur;
if (surfaceShim.graphicBufferProducer != nullptr)
// IGraphicBufferProducer 不同
// 且 surfaceShim 的 IGraphicBufferProducer 不为空
// 创建一个新的 Surface 对象 sur
sur = new Surface(surfaceShim.graphicBufferProducer, true);
sur->incStrong(&sRefBaseOwner);
…
// 将 sur 的指针返回给 Java 层
return jlong(sur.get());
到这里我们不难看出
Java层
的Surface
对象最重要的数据是mNativeObject
变量mNativeObject
是一个指针,指向的native
层的Surface
对象native
层在判断是否新建Surface
对象的逻辑依赖的是IGraphicBufferProducer
对象IGraphicBufferProducer
对象是一个Binder
引用对象
那么接下来我们重点就是这个IGraphicBufferProducer
了。
我们先看下native层
中Surface
类的继承关系:
-
class Surface
- public ANativeObjectBase<ANativeWindow, Surface, RefBase>
ANativeObjectBase
的定义如下:
template <typename NATIVE_TYPE, typename TYPE, typename REF,
typename NATIVE_BASE = android_native_base_t>
class ANativeObjectBase : public NATIVE_TYPE, public REF
…
整理成继承关系图就是:
再看下Surface
的构造方法:
-
Surface::Surface(const sp& bufferProducer, bool controlledByApp)
-
mGraphicBufferProducer(bufferProducer),
mCrop(Rect::EMPTY_RECT),
mBufferAge(0),
…
mFrameEventHistory(std::make_unique())
… // 初始化各种成员变量
从构造函数的参数可以看到,native层
的Surface
将IGraphicBufferProducer
对象保存到了mGraphicBufferProducer
变量中。
暂时还是不清楚mGraphicBufferProducer
哪里来的,我们去WMS
中看看
WMS
中Surface
的创建过程
此处要从Activity
的onResume()
生命周期说起
onResume()
到WMS.relayoutWindow()
我们已经知道,当AMS
触发onResume()
生命周期时会调用到ActivityThread
类的handleResumeActivity()
方法,代码如下:
public void handleResumeActivity(…)
…
// 此处会触发 onResume 声明周期回调
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
…
ViewManager wm = a.getWindowManager();
…// 省略很多 Window 处理逻辑
wm.addView(decor, l);
…
从方法中可以看到,执行完onResume()
后调用了ViewManager
的addView(decor, l)
方法
知识点:在
onResume
方法调用后才真正进行View
的添加
ViewManager
是一个接口类,真正的实现类是WindowManagerImpl
,addView()
方法实现也很简单:
public void addView(…)
applyDefaultToken(params);
mGlobal.addView(…);
调用了mGlobal
的addView()
方法方法,mGlobal
的类型是WindowManagerGlobal
,代码如下:
public void addView(…)
…
ViewRootImpl root;
synchronized (mLock)
…
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
try
root.setView(view, wparams, panelParentView);
…
WindowManagerGlobal
类的addView()
先是创建了一个新的ViewRootImpl
对象,然后调用了ViewRootImpl
对象的setView()
方法。
ViewRootImpl
类中setView()
调用流程如下:
class ViewRootImpl
/**
- 这里也是直接 new 出来的对象 Surface
- 前面已经介绍过,这个对象需要和 native层进行绑定后才能正常使用
*/
public final Surface mSurface = new Surface();
ViewRootImpl(Context context, Display display)
…
// 此方法会创建 Session 对象
mWindowSession = WindowManagerGlobal.getWindowSession();
…
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView)
synchronized (this)
if (mView == null)
mView = view;
…
// 内部方法调用
requestLayout();
…
// 此方法会创建 SurfaceSession
res = mWindowSession.addToDisplay(…);
…
public void requestLayout()
if (!mHandlingLayoutInLayoutRequest)
…
scheduleTraversals();
void scheduleTraversals()
if (!mTraversalScheduled)
…
// 异步执行 mTraversalRunnable
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
…
final class TraversalRunnable implements Runnable
@Override
public void run()
doTraversal();
void doTraversal()
if (mTraversalScheduled)
…
performTraversals();
…
private void performTraversals()
…
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
…
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException
…
// 调用 mWindowSession 的 relayout 方法,并将 mSurface 对象传递过去
int relayoutResult = mWindowSession.relayout(…, mSurface);
…
return relayoutResult;
setView()
方法最后调用的是mWindowSession
的relayout()
方法。
mWindowSession
类型是IWindowSession
,是一个Binder
引用对象。真正的Binder
服务实现是com.android.server.wm.Session
类:
class Session extends IWindowSession.Stub implements IBinder.DeathRecipient
public Session(WindowManagerService service, …)
mService = service;
…
public int relayout(…, Surface outSurface)
…
int res = mService.relayoutWindow(…, outSurface);
…
return res;
终于走到了WMS
中,调用的是WMS
的relayoutWindow()
方法
WMS.relayoutWindow()
到SurfaceControl.nativeCreate()
和Surface
相关的调用关系如下:
class WindowManagerService
public int relayoutWindow(…, Surface outSurface)
…
result = createSurfaceControl(outSurface, …);
…
return result;
private int createSurfaceControl(Surface outSurface, …)
…
WindowSurfaceController surfaceController;
…
surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
…
if (surfaceController != null)
surfaceController.getSurface(outSurface);
else
…
outSurface.release();
return result;
class WindowSurfaceController
public WindowSurfaceController(…)
…
final SurfaceControl.Builder b = win.makeSurface()
…
.setMetadata(windowType, ownerUid);
mSurfaceControl = b.build();
void getSurface(Surface outSurface)
outSurface.copyFrom(mSurfaceControl);
class Surface
public void copyFrom(SurfaceControl other)
if (other == null)
throw new IllegalArgumentException(“other must not be null”);
long surfaceControlPtr = other.mNativeObject;
if (surfaceControlPtr == 0)
throw new NullPointerException(
“null SurfaceControl native object. Are you using a released SurfaceControl?”);
long newNativeObject = nativeGetFromSurfaceControl(surfaceControlPtr);
synchronized (mLock)
if (mNativeObject != 0)
nativeRelease(mNativeObject);
setNativeObjectLocked(newNativeObject);
在上面的relayoutWindow()
方法中
WMS
先通过winAnimator
的createSurfaceLocked()
方法得到了一个WindowSurfaceController
对象WindowSurfaceController
对象封装了SurfaceControl
对象- 然后
WMS
调用WindowSurfaceController
对象的getSurface()
方法来对Surface
对象进行填充 getSurface()
对象只是利用自身保存的mSurfaceControl
对象- 通过
Surface
的copyFrom()
方法对Surface
对象进行填充处理 copyFrom()
方法- 调用
nativeGetFromSurfaceControl()
方法得到一个native
层的Surface
对象指针 - 然后通过
setNativeObjectLocked()
方法将指针保存到成员变量mNativeObject
中
关键点又回到了native
层的nativeGetFromSurfaceControl()
方法,它的代码如下:
static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz,
jlong surfaceControlNativeObj)
sp ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
sp surface(ctrl->getSurface());
if (surface != NULL)
surface->incStrong(&sRefBaseOwner);
return reinterpret_cast(surface.get());
nativeGetFromSurfaceControl()
方法是通过native
层的SurfaceControl
的getSurface()
方法来获取Surface
对象。我们再看下getSurface()
方法:
sp SurfaceControl::getSurface() const
Mutex::Autolock _l(mLock);
if (mSurfaceData == 0)
return generateSurfaceLocked();
return mSurfaceData;
sp SurfaceControl::generateSurfaceLocked() const
mSurfaceData = new Surface(mGraphicBufferProducer, false);
return mSurfaceData;
在SurfaceControl
的getSurface()
方法中
- 当
mSurfaceData
指针为空时才会通过generateSurfaceLocked()
方法创建一个新的Surface
对象 Surface
对象中很关键的IGraphicBufferProducer
在这里传入的是SurfaceControl
的成员变量mGraphicBufferProducer
- 否则直接返回
mSurfaceData
指针
从getSurface()
方法的逻辑中我们不难看出,SurfaceControl
对象和Surface
对象是关联在一起的,一对一的关系
更关键的是构造Surface
对象的核心参数竟然是SurfaceControl
中的成员变量。。。。。。。。
没办法,要先搞定SurfaceControl
的创建过程才可以
前面已经讲过,WMS
通过winAnimator.createSurfaceLocked()
方法创建了WindowSurfaceController
对象,WindowSurfaceController
对象初始化时就会创建SurfaceControl
,我们看下创建过程:
class WindowStateAnimator
WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid)
…
// mSession 的类型就是前面提到的 Session 类,IWindowSession Binder服务类
mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession, …);
…
return mSurfaceController;
class WindowSurfaceController
public WindowSurfaceController(SurfaceSession s, …)
…
final SurfaceControl.Builder b = win.makeSurface()
…
.setMetadata(windowType, ownerUid);
// 通过 Builder 模式创建的
mSurfaceControl = b.build();
class SurfaceControl
public static class Builder
…
public SurfaceControl build()
…
// 调用私有构造方法
return new SurfaceControl(mSession, …);
…
private SurfaceControl(SurfaceSession session, …)
throws OutOfResourcesException, IllegalArgumentException
…
mNativeObject = nativeCreate(session, …);
if (mNativeObject == 0)
throw new OutOfResourcesException(
“Couldn’t allocate SurfaceControl native object”);
…
可以看到
- 创建
SurfaceControl
对象的全程都携带着一个SurfaceSession
对象。 - 同时这个
SurfaceSession
对象在SurfaceControl
的构造方法中通过nativeCreate()
传递到了native层
,用来创建native层
的对象 - 和
Java层
的Surface
对象一样,SurfaceControl
对象也会将native层
对象的指针保存到mNativeObject
中
关键还是在nativeCreate()
方法,我们继续。。
nativeCreate()
方法如下:
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj, …)
ScopedUtfChars name(env, nameStr);
sp client(android_view_SurfaceSession_getClient(env, sessionObj));
…
sp surface;
status_t err = client->createSurfaceChecked(
String8(name.c_str()), w, h, format, &surface, flags, parent, windowType, ownerUid);
…
return reinterpret_cast(surface.get());
nativeCreate()
方法中又出现了一个新的类型SurfaceComposerClient
,而且native层
的SurfaceControl
对象就是通过它的createSurfaceChecked()
来创建的
耐心、耐心、耐心。。。。 崩溃的时候多说几次
上面方法中的SurfaceComposerClient
对象是通过android_view_SurfaceSession_getClient()
方法得到的,看JNI
的命名格式可以推算它和SurfaceSession
类也有关系,内容如下:
sp android_view_SurfaceSession_getClient(
JNIEnv* env, jobject surfaceSessionObj)
return reinterpret_cast<SurfaceComposerClient*>(
env->GetLongField(surfaceSessionObj, gSurfaceSessionClassInfo.mNativeClient));
android_view_SurfaceSession_getClient()
方法中的参数surfaceSessionObj
是在Java层
调用nativeCreate()
方法时传递的参数,类型是SurfaceSession
。
这里实际上是将
SurfaceSession
对象中成员变量mNativeClient
的值取出来后,转换为SurfaceComposerClient
对象返回
这说明SurfaceComposerClient
对象和SurfaceSession
对象也是一起创建出来的,我们继续看下SurfaceSession
和SurfaceComposerClient
的创建过程
SurfaceControl.nativeCreate
到ComposerService
需要知道的一个重要前提:每个用户进程在
WMS
中都有且只有一个对应的Session
对象,前面已经介绍Session
是一个实现了IWindowSession
接口的Binder
服务类
Session
的成员变量mSurfaceSession
是在Session
对象初始化时创建的,那么Session
对象在什么时候创建的呢?
跟踪代码发现流程如下:
ViewRootImpl
初始化时会调用WindowManagerGlobal.getWindowSession()
方法WindowManagerGlobal.getWindowSession()
会调用WMS
的openSession()
方法openSession()
方法中便会在WMS
中创建一个新的Session
对象
对于SurfaceSession
的初始化,是在Session
对象的windowAddedLocked()
方法中,那么windowAddedLocked()
方法又是在哪里调用的呢?
同样,我们跟踪下方法调用:
ViewRootImpl
的setView()
方法中会调用mWindowSession.addToDisplay(...)
方法mWindowSession.addToDisplay(...)
方法会调用WMS
的addWindow()
方法WMS
的addWindow()
方法会调用WindowState
的attach()
方法attach()
方法会调用Session
的windowAddedLocked()
方法
这样就串起来了,现在我们可以继续学习SurfaceSession
的构造方法了:
/** Create a new connection with the surface flinger. */
public SurfaceSession()
mNativeClient = nativeCreate();
很简洁,源码注释也很关键。我们看下SurfaceSession
的nativeCreate()
方法:
static jl
ong nativeCreate(JNIEnv* env, jclass clazz)
SurfaceComposerClient* client = new SurfaceComposerClient();
// 请注意此方法的调用
// 该方法会触发 onFirstRef() 的执行
client->incStrong((void*)nativeCreate);
return reinterpret_cast(client);
nativeCreate()
直接创建了一个SurfaceComposerClient
对象,也没有参数。不过SurfaceComposerClient
类是从RefBase
类派生出来的,我们看下它的构造函数和onFirstRef
函数:
-
SurfaceComposerClient::SurfaceComposerClient()
-
mStatus(NO_INIT)
// onFirstRef() 是 RefBase 提供的回调接口
// 当首次调用 incStrong() 方法时便会执行此方法
void SurfaceComposerClient::onFirstRef()
sp sf(ComposerService::getComposerService());
if (sf != 0 && mStatus == NO_INIT)
// 此处 rootProducer 应该为 null
auto rootProducer = mParent.promote();
sp conn;
// 所以在此处执行的是 sf->createConnection() 方法
conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
sf->createConnection();
if (conn != 0)
mClient = conn;
mStatus = NO_ERROR;
构造方法很简单,只是将mStatus
设置为NO_INIT
。
重点是在onFirstRef()
方法中
- 先调用了
ComposerService
的getComposerService()
方法来得到一个ISurfaceComposer
的指针 - 然后调用它的
createConnection()
方法创建一个ISurfaceComposerClient
对象 - 然后将
mClient
指向这个ISurfaceComposerClient
对象
咳咳咳,按照上面的调用流程我们还没有找到关于
IGraphicBufferProducer
的信息,现在又多出来了一个ISurfaceComposerClient
。。。
好吧好吧,梳理下这部分关系先
WMS
中Surface
关系总结
上面介绍的WMS
中涉及和Surface
有关的类关系如下:
看上去就挺复杂的:
SurfaceControl
和Surface
是成对创建的,考虑到绘制等需求,它们的数量会比较多Session
、SurfaceSession
和SurfaceComposerClient
对象是和连接WMS
的用户进程的数量相同SurfaceComposerClient
的作用是创建Surface
SurfaceControl
通过SurfaceComposerClient
来获取Surface
SurfaceComposerClient
是ComposerService
的具体实现类
ComposerService
再到SurfaceFlinger
ComposerService
是一个单例模式的普通类,定义如下:
class ComposerService : public Singleton
sp mComposerService;
spIBinder::DeathRecipient mDeathObserver;
Mutex mLock;
ComposerService();
void connectLocked();
void composerServiceDied();
friend class Singleton;
public:
static sp getComposerService();
;
前面的onFirstRef()
方法中调用了ComposerService
类的静态方法getComposerService()
,我们看下它的实现:
/static/ sp ComposerService::getComposerService()
ComposerService& instance = ComposerService::getInstance();
Mutex::Autolock _l(instance.mLock);
if (instance.mComposerService == NULL)
ComposerService::getInstance().connectLocked();
…
return instance.mComposerService;
getComposerService()
通过调用父类Singleton
的getInstance()
方法来取得实例对象,然后调用ComposerService
的connectLocked()
方法:
void ComposerService::connectLocked()
();
void composerServiceDied();
friend class Singleton;
public:
static sp getComposerService();
;
前面的onFirstRef()
方法中调用了ComposerService
类的静态方法getComposerService()
,我们看下它的实现:
/static/ sp ComposerService::getComposerService()
ComposerService& instance = ComposerService::getInstance();
Mutex::Autolock _l(instance.mLock);
if (instance.mComposerService == NULL)
ComposerService::getInstance().connectLocked();
…
return instance.mComposerService;
getComposerService()
通过调用父类Singleton
的getInstance()
方法来取得实例对象,然后调用ComposerService
的connectLocked()
方法:
void ComposerService::connectLocked()
Android 深入系统完全讲解(23)
OpenGL 和 OpenGLES 简介
OpenGL(Open Graphics Library)意为开放图形库,是一个跨平台的图形 API,用于指定 3D 图
形处理硬件中的软硬件编程接口。OpenGL 一般用于图形工作站,PC 端使用。由于性能和可
移植性等各方面原因,在移动端使用起来相对比较麻烦。为此,Khronos 公司就为 OpenGL
提供一个子集,OpenGL ES(OpenGL for Embedded System)。OpenGL ES 是免费的跨平台且功
能完善的 2D/3D 图形库接口 API,是 OpenGL 的一个子集。
使用 OpenGLES 可以直接用 GPU 进行运算,专门来处理图像,会加速整体的性能,这是它存
在的意义。
在 Android 里面,GLSurfaceView 承载这个任务。GLSurfaceView 在 SurfaceView 的上面,将
Surface 用 EGL 进行处理,完成了可以使用 OpenGLES 绘制,关联到对应的 Surface。使用 GLSurfaceView
下来我们讲解下,如何使用它。
1 在 AndroidManifest.xml 中设置版本,
关
然后在主界面里面:
glSurfaceView = (GLSurfaceView) findViewById(R.id.glSurfaceView);
//GLContext 设置 OpenGLES2.0
glSurfaceView.setEGLContextClientVersion(2);
// 在 setRenderer 之前,可以调用以下方法进行 EGL 设置
// glSurfaceView.setEGLConfigChooser(true);//颜色,深度,模板等等设置
// glSurfaceView.setEGLWindowSurfaceFactory(new GLSurfaceView.EGLWindowSurfaceFactory() //窗口设置
// @Override
// public EGLSurface createWindowSurface(EGL10 egl10, EGLDisplay eglDisplay, EGLConfig eglConfig, Object o)
// return null;
//
//
// @Override
// public void destroySurface(EGL10 egl10, EGLDisplay eglDisplay, EGLSurface eglSurface)
//
//
// );
glSurfaceView.setRenderer(new TriangleRender());
/* 渲 染 方 式 , RENDERMODE_WHEN_DIRTY 表 示 被 动 渲 染 , 只 有 在 调 用
requestRender 或者 onResume 等方法时才会进行渲染。RENDERMODE_CONTINUOUSLY 表
示持续渲染*/
glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
两种渲染方式,持续渲染是在需要高速显示的情况下才需要,默认直接选择只有脏了才需要。
这里我们主要的任务,就是设置一个渲染器。
public class BackgroundRender extends BaseRenderer implements GLSurfaceView.Renderer
private String TAG = BackgroundRender.class.getSimpleName();
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig)
//surface 被创建后需要做的处理
//Set the background frame color
GLES20.glClearColor(0.0f,0.0f,0.0f,1.0f);
@Override
public void onSurfaceChanged(GL10 gl10, int width, int height)
// 渲染窗口大小发生改变或者屏幕方法发生变化时候回调
GLES20.glViewport(0,0,width,height);
@Override
public void onDrawFrame(GL10 gl10)
//执行渲染工作
//Redraw background color
GLES20.glClearColor(GLES20.GL_COLOR_BUFFER_BIT,0f,0f,0f); 这里是完成每一帧
的渲染动作
在实际的使用过程中,会遇见所谓的 OpenGL 编程语言,牵扯到顶点渲染和着色渲染,这块
属于专门的 OpenGLES 的知识,在做 GPU 特效的时候,可以去研究。
这里推荐一个库 GPUImage ,是一个安卓的图片处理特效库,当我们后面学会了解析视频,
渲染每一帧的时候,可以给它使用特效。
以上是关于深入Android系统Android图形显示系统-1-显示原理与Surface的主要内容,如果未能解决你的问题,请参考以下文章