1、Surface图形系统概览
Surface是一个显示系统中的组件,无论是在图形系统的结构之中,还是在生产消费模型的流程之中都做作为一个举足轻重的角色,参与整个安卓的显示生命周期之中。
我们摘抄了两段谷歌对surface的描述作为贯穿整个文章的中心:
1.A surface is an interface for a producer to exchange buffers with a consumer.
2.No matter what rendering API developers use, everything is rendered onto a surface. The surface represents the producer side of a buffer queue that is often consumed by SurfaceFlinger. Every window that is created on the Android platform is backed by a surface.
- 下图是安卓官网对于安卓图形架构组成的说明
- 其中High-level components 是在编写安卓程序时使用到的具体类,安卓app通过控制这些工具,来间接控制surface在底层的使用。
- 其中Low-level components 是真正属于在framework层中的图形显示实践。
- 下图是整个Low-level components的Graphic Oerview,着重说明了整个显示系统的流转。我们从每个组件,每个箭头来一一分析。
我们将整个过程当做一次美术博物馆的展出,便于理解这些组件在显示过程中的作用。
1.1 IMAGE STREAM PRODUCERS
位于生产消费模型的生产端,所有可以生成buffer data 的内容。读取media中的内容,读取camera中的内容,用NDK生成图像,用OpenGL生成图像等等。他们都可以作为纯粹的画家,也就是内容生产者。
他们既决定Buffer Data中的内容,也同时决定“取景框”Windows的大小位置。
1.2 NATIVE FRAMEWORK
- 在native framework层中,libgui负责构建buffer队列,安排buffer的消费者,组织有序的生产和消费流程。
- 可以理解为“不懂画但是手握画品的拍卖工厂”。
1.3 WINDOW POSITIONING
- 大部分显示系统,无论安卓、windows、qnx都会需要一个window管理,用来管理不同buffer的大小、层级、位置等等信息,在一个屏幕中,尽可能的配合所有画面的内容。
- 相当于“杂志的排版编辑”
1.4 IMAGE STREAM CONSUMERS
- 自此真正的消费者出现了,他们根据排版编辑的排列信息,去到拍卖工厂中的GraphicBufferQueue中,整合信息将展览画面传到屏幕中。SurfaceFlinger会与HWC通信,决定由谁来合成layer画面。
1.5 HAL
- 硬件部分的内容,HWC是Android中进行窗口(Layer)合成和显示的HAL层模块,Gralloc是用于给graphicbuffer申请内存地址的。
2 Surface的创建
surface在很多层面都有自己的属性,从base到native。由上而下来看看surface到底是怎么创建的。
2.1 构造函数
- 第一层:java接口调用
- 位置:/frameworks/base/core/java/android/view/Surface.java
/**
* Create an empty surface, which will later be filled in by readFromParcel().
* @hide
*/
public Surface() {
}
/**
* Create Surface from a {@link SurfaceTexture}.
*
* Images drawn to the Surface will be made available to the {@link
* SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link
* SurfaceTexture#updateTexImage}.
*
* Please note that holding onto the Surface created here is not enough to
* keep the provided SurfaceTexture from being reclaimed. In that sense,
* the Surface will act like a
* {@link java.lang.ref.WeakReference weak reference} to the SurfaceTexture.
*
* @param surfaceTexture The {@link SurfaceTexture} that is updated by this
* Surface.
* @throws OutOfResourcesException if the surface could not be created.
*/
public Surface(SurfaceTexture surfaceTexture) {
....
mIsSingleBuffered = surfaceTexture.isSingleBuffered();
synchronized (mLock) {
mName = surfaceTexture.toString();
setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
}
}
/* called from android_view_Surface_createFromIGraphicBufferProducer() */
private Surface(long nativeObject) {
synchronized (mLock) {
setNativeObjectLocked(nativeObject);
}
}
Surface类对外有两个构造方法,对内一种:
- 第一个是无参构造,实现也是空的,主要是给
readFromParcel()
反序列化用的
public void readFromParcel(Parcel source) {
...
synchronized (mLock) {
mName = source.readString();
mIsSingleBuffered = source.readInt() != 0;
setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
}
}
- 第二个是针对GPU绘制内容的,绑定surfacetexture
- 此时Surface是生产者,SurfaceTexture(Native层对应GLConsumer)是消费者。消费者负责把从BufferQueue中获取的GraphicBuffer转换为纹理,然后业务层可以对纹理进一步处理,例如:上特效或者上屏。
- 第三个是由android_view_Surface_createFromIGraphicBufferProducer函数调用的,如media/ImageReader中的getsurface方法
static jobject ImageReader_getSurface(JNIEnv* env, jobject thiz)
{
...
IGraphicBufferProducer* gbp = ImageReader_getProducer(env, thiz);
...
// Wrap the IGBP in a Java-language Surface.
return android_view_Surface_createFromIGraphicBufferProducer(env, gbp);
}
2.1.1 setNativeObjectLocked
- 仔细看上述三个构造函数,无论是私有办法,还是共有办法,都会调用一个函数
setNativeObjectLocked()
,区别在与参数的不同
- 私有办法:
setNativeObjectLocked(nativeObject);
- 无参数:
setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
- 绑定surfacetexture:
setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
private void setNativeObjectLocked(long ptr) {
if (mNativeObject != ptr) {
...
//只是更新了变量的数值,只是针对不同数据来源的处理
//其中最重要的是mNativeObject 是一个指向native 层surface的指针
mNativeObject = ptr;
...
}
}
2.2 native 层
2.2.1 nativeReadFromParcel
- 进入native层的第一个内容就是
nativeReadFromParcel(mNativeObject, source)
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<Surface> 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<Surface> 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());
}
- 传入native层中的surface对象为surfaceshim ,将此内容传入native层的surface中,注意这个surfaceshim需要持有一个graphicBufferProducer以此生成一个新的surface对象。
2.2.2 android_view_Surface_createFromIGraphicBufferProducer
- 通过bufferProducer建立新的surface对象
jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
const sp<IGraphicBufferProducer>& bufferProducer) {
if (bufferProducer == NULL) {
return NULL;
}
sp<Surface> surface(new Surface(bufferProducer, true));
return android_view_Surface_createFromSurface(env, surface);
}
2.2.3 nativeCreateFromSurfaceTexture(surfaceTexture)
static jlong nativeCreateFromSurfaceTexture(JNIEnv* env, jclass clazz,
jobject surfaceTextureObj) {
sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, surfaceTextureObj));
...
sp<Surface> surface(new Surface(producer, true));
...
surface->incStrong(&sRefBaseOwner);
return jlong(surface.get());
}
2.2.4 native 中的surface构造函数
不难看出所有的surface创建中,都需要一个IGraphicBufferProducer
对象作为参数,而IGraphicBufferProducer
对象是一个Binder
引用对象,BufferQueue的生产者接口,实现类是BufferQueueProducer
- 注释中还贴心的说明了Surface是ANativeWindow的一种实现,它将图形缓冲区馈送到BufferQueue中
/*
* An implementation of ANativeWindow that feeds graphics buffers into a
* BufferQueue.
*/
class Surface
//ANativeObjectBase,属于模板的一部分
//class ANativeObjectBase : public NATIVE_TYPE, public REF
: public ANativeObjectBase<ANativeWindow, Surface, RefBase>
public:
/*
* creates a Surface from the given IGraphicBufferProducer (which concrete
* implementation is a BufferQueue).
*
* Surface is mainly state-less while it's disconnected, it can be
* viewed as a glorified IGraphicBufferProducer holder. It's therefore
* safe to create other Surfaces from the same IGraphicBufferProducer.
*
* However, once a Surface is connected, it'll prevent other Surfaces
* referring to the same IGraphicBufferProducer to become connected and
* therefore prevent them to be used as actual producers of buffers.
*
* the controlledByApp flag indicates that this Surface (producer) is
* controlled by the application. This flag is used at connect time.
*/
Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp = false);
private:
// mSurfaceTexture is the interface to the surface texture server. All
// operations on the surface texture client ultimately translate into
// interactions with the server using this interface.
// TODO: rename to mBufferProducer
// native层的Surface将IGraphicBufferProducer对象保存到了mGraphicBufferProducer变量中。
sp<IGraphicBufferProducer> mGraphicBufferProducer;
- 继承关系图如下,那么问题来了,mGraphicBufferProducer是从哪里来的呢
- 第一:直接从 GraphicBufferProducer创建Surface
- 第二:直接从SurfaceTexture创建
- 第三:就要从surfaceShim.graphicBufferProducer,也就是上一层来获取
2.3 总结
- 所有surface在native的构建都需要一个graphicbufferproducer作为参数。而这也真好印证了
1.2 NATIVE FRAMEWORK
中所提到的 - surface在java层由三种构建方式,同样对于IGraphicBufferProducer也有不同的渠道获得。