深入Android系统Android图形显示系统-1-显示原理与Surface

Posted 智恩架构师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入Android系统Android图形显示系统-1-显示原理与Surface相关的知识,希望对你有一定的参考价值。

  • Window Positioning中的WindowManager主要是用来控制Window对象

  • Window对象是用来存放View对象的容器,每个Window对象都会关联Surface对象

  • WindowManager监视Window对象的生命周期、输入和焦点事件、屏幕方向、转换、动画、位置、变换、z顺序等

  • 然后将所有Window元数据发送给SurfaceFlingerSurfaceFlinger利用这些元数据把自己管理的所有Surface组合成layer

  • 然后交给Hardware Composer做进一步处理

  • HAL层中的Hardware Composer(HWC)会根据当前硬件来进一步进行缓冲区的组合,它的具体实现依赖于特定的显示设备

  • 官网关于HWC的数据流如下:

  • SurfaceFlinger作为clientHWC提供一个完整的layer列表,然后询问HWC计划如何处理
  • HWC会将这些layer标记为client合成或者device合成并告知SurfaceFlinger
  • SurfaceFlinger将处理标记为client合成layer,然后通过BufferQueue传递给HWC
  • 余下的layerHWC自行处理

网上一篇很有趣的渲染总结(文中有些错误,但瑕不掩瑜):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充当了中间衔接的角色。

ActivityUI显示为例:

  • 生产者的任务就是把图形绘制在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层SurfaceIGraphicBufferProducer对象保存到了mGraphicBufferProducer变量中。

暂时还是不清楚mGraphicBufferProducer哪里来的,我们去WMS中看看

WMSSurface的创建过程

此处要从ActivityonResume()生命周期说起

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()后调用了ViewManageraddView(decor, l)方法

知识点:onResume方法调用后才真正进行View的添加

ViewManager是一个接口类,真正的实现类是WindowManagerImpladdView()方法实现也很简单:

public void addView(…)
applyDefaultToken(params);
mGlobal.addView(…);

调用了mGlobaladdView()方法方法,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()方法最后调用的是mWindowSessionrelayout()方法。

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中,调用的是WMSrelayoutWindow()方法

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先通过winAnimatorcreateSurfaceLocked()方法得到了一个WindowSurfaceController对象
  • WindowSurfaceController对象封装了SurfaceControl对象
  • 然后WMS调用WindowSurfaceController对象的getSurface()方法来对Surface对象进行填充
  • getSurface()对象只是利用自身保存的mSurfaceControl对象
  • 通过SurfacecopyFrom()方法对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层的SurfaceControlgetSurface()方法来获取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;

SurfaceControlgetSurface()方法中

  • 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对象也是一起创建出来的,我们继续看下SurfaceSessionSurfaceComposerClient的创建过程

SurfaceControl.nativeCreateComposerService

需要知道的一个重要前提:每个用户进程在WMS中都有且只有一个对应的Session对象,前面已经介绍Session是一个实现了IWindowSession接口的Binder服务类

Session的成员变量mSurfaceSession是在Session对象初始化时创建的,那么Session对象在什么时候创建的呢?
跟踪代码发现流程如下:

  • ViewRootImpl初始化时会调用WindowManagerGlobal.getWindowSession()方法
  • WindowManagerGlobal.getWindowSession()会调用WMSopenSession()方法
  • openSession()方法中便会在WMS中创建一个新的Session对象

对于SurfaceSession的初始化,是在Session对象的windowAddedLocked()方法中,那么windowAddedLocked()方法又是在哪里调用的呢?
同样,我们跟踪下方法调用:

  • ViewRootImplsetView()方法中会调用mWindowSession.addToDisplay(...)方法
  • mWindowSession.addToDisplay(...)方法会调用WMSaddWindow()方法
  • WMSaddWindow()方法会调用WindowStateattach()方法
  • attach()方法会调用SessionwindowAddedLocked()方法

这样就串起来了,现在我们可以继续学习SurfaceSession的构造方法了:

/** Create a new connection with the surface flinger. */
public SurfaceSession()
mNativeClient = nativeCreate();

很简洁,源码注释也很关键。我们看下SurfaceSessionnativeCreate()方法:

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()方法中

  • 先调用了ComposerServicegetComposerService()方法来得到一个ISurfaceComposer的指针
  • 然后调用它的createConnection()方法创建一个ISurfaceComposerClient对象
  • 然后将mClient指向这个ISurfaceComposerClient对象

咳咳咳,按照上面的调用流程我们还没有找到关于IGraphicBufferProducer的信息,现在又多出来了一个ISurfaceComposerClient。。。

好吧好吧,梳理下这部分关系先

WMSSurface关系总结

上面介绍的WMS中涉及和Surface有关的类关系如下:

看上去就挺复杂的:

  • SurfaceControlSurface是成对创建的,考虑到绘制等需求,它们的数量会比较多
  • SessionSurfaceSessionSurfaceComposerClient对象是和连接WMS的用户进程的数量相同
  • SurfaceComposerClient的作用是创建Surface
  • SurfaceControl通过SurfaceComposerClient来获取Surface
  • SurfaceComposerClientComposerService的具体实现类

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()通过调用父类SingletongetInstance()方法来取得实例对象,然后调用ComposerServiceconnectLocked()方法:

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()通过调用父类SingletongetInstance()方法来取得实例对象,然后调用ComposerServiceconnectLocked()方法:

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的主要内容,如果未能解决你的问题,请参考以下文章

Android 深入系统完全讲解(23)

从整体上看Android图像显示系统

从整体上看Android图像显示系统

Android 图形架构 之五—— 深入分析addView所发生的的一切

Android图形系统系统篇之HWC

Android 图形架构 之五—— 深入分析addView所发生的的一切