Android绘制系统(1): Surface - clarkehe/Android GitHub Wiki

Android绘制系统比较复杂,核心是surfaceFlinger(很多有经验的开发人员不认识这个独立服务进程),还有很多的概念(类)。从去年就开始断断续续看了一些源码与别人写的博客文章,有了一个大概的了解。但不太全面,有细节也不够深入。只能边了解一点,边记录一点,后面再慢慢的串起来。先从Surface讲起吧。

Surface的是什么?

Surface在Android的绘制系统是一个承上启下的类。上向View提供画布Canvas,下向surfaceFlinger提供可显示的缓存。在surfaceFlinger眼中是没有View这些概念的,它只关心图像缓存。View树绘制出来的图像通过Surface提交给了surfaceFlinger进行合成显示。

在Java层(Surface.java),Surface有两个核心的接口:lockCanvas和unlockCanvasAndPost。lockCanvas返回一个Canvas供View进行绘制,unlockCanvasAndPost则提交绘制的结果。

再看看Native层的Surface(Surface.hSurface.cpp)。

Native层的Surface是ANativeWindow(window.h)的一个实现。ANativeWindow是Android针对OpenGL ES的窗口实现。ANativeWindow联接了OpenGL与Surface。Surface通过ANativeWindow为OpenGL提供要栅格化时需要的缓存(硬件绘制的时候,将命令转化为像素位图)。

class Surface
    : public ANativeObjectBase<ANativeWindow, Surface, RefBase>
{
public:
...

Surface对外提供了获取可用缓存的接口,Surface是可以无视ANativeWindow独立存在的(个人理解),比如Skia 2D软绘制的时候。ANativeWindow的实现接口最终都转为对Surface的接口的调用,类似一种接口转换模式。OpenGL在栅格化时,找ANativeWindow要缓存,ANativeWindow自己没有缓存,将请求转给了Surface,由Surface来提供缓存。

ViewRootImpl.java中软绘制时,Surface的使用。这也是软件绘制的入口及基本流程。

    private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
            boolean scalingRequired, Rect dirty) {

        // Draw with software renderer.
        final Canvas canvas;
        try {
            canvas = mSurface.lockCanvas(dirty);
        } 
        ...
        try {
            ...
            try {
                ...
                mView.draw(canvas);
            }
            ....
        } finally {
            try {
                surface.unlockCanvasAndPost(canvas);
            } 
            ...
        }
        return true;
    }

这样Surface在绘制时,有两种使用途径。一种是软绘制的时候,直接使用其lockCanvas与unlockCanvasAndPost接口;另一种是硬件绘制的时候,通过ANativeWindow向OpenGL提供缓存。本质都一样的,都是缓存的获取,数据填充,缓存提交。

Surfacer的创建

Java层Surface对象的创建主要有三种方式。
一是JAVA反射方法创建(android_view_Surface.cpp),这种方式用的地方很多,ImageReader的Surface就是这处方式创建。

    /* called from android_view_Surface_createFromIGraphicBufferProducer() */
    private Surface(long nativeObject) {
        synchronized (mLock) {
            setNativeObjectLocked(nativeObject);
        }
    }
jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
        const sp<IGraphicBufferProducer>& bufferProducer) {
    if (bufferProducer == NULL) {
        return NULL;
    }
     
    //Native层Surface的创建,构造参数有一个非常关键的:bufferProducer
    sp<Surface> surface(new Surface(bufferProducer, true));
    if (surface == NULL) {
        return NULL;
    }

    //调用JAVA层Surface的构造方法,Java层的Surface只是一个壳,通过一个long型值引用Native层的Surface
    jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz,
            gSurfaceClassInfo.ctor, (jlong)surface.get());
    if (surfaceObj == NULL) {
        if (env->ExceptionCheck()) {
            ALOGE("Could not create instance of Surface from IGraphicBufferProducer.");
            LOGE_EX(env);
            env->ExceptionClear();
        }
        return NULL;
    }
    surface->incStrong(&sRefBaseOwner);
    return surfaceObj;
}

二是复制创建([Surface.java] (http://androidxref.com/5.0.0_r2/xref/frameworks/base/core/java/android/view/Surface.java#311)),Activity背后的Surface就是这种方式创建的。

    /**
     * Copy another surface to this one.  This surface now holds a reference
     * to the same data as the original surface, and is -not- the owner.
     * This is for use by the window manager when returning a window surface
     * back from a client, converting it from the representation being managed
     * by the window manager to the representation the client uses to draw
     * in to it.
     * @hide
     */
    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(
                    "SurfaceControl native object is null. Are you using a released SurfaceControl?");
        }
        long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);

        synchronized (mLock) {
            if (mNativeObject != 0) {
                nativeRelease(mNativeObject);
            }
            setNativeObjectLocked(newNativeObject);
        }
    }

第三种是通过SurfaceTexture来创建([Surface.java] (http://androidxref.com/5.0.0_r2/xref/frameworks/base/core/java/android/view/Surface.java#133)),这种方式不太常见。 使用这种方式,就需要先创建一个SurfaceTexture,而创建SurfaceTexture则需求一个texture id。后面再专门讲SurfaceTexture及其创建。

    public Surface(SurfaceTexture surfaceTexture) {
        if (surfaceTexture == null) {
            throw new IllegalArgumentException("surfaceTexture must not be null");
        }

        synchronized (mLock) {
            mName = surfaceTexture.toString();
            setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
        }
    }
    /**
     * Construct a new SurfaceTexture to stream images to a given OpenGL texture.
     *
     * @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
     *
     * @throws Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
     */
    public SurfaceTexture(int texName) {
        this(texName, false);
    }

Native层的Surface(Surface.cpp)创建就一种方法,构造函数中传入一个IGraphicBufferProducer参数。

Surface::Surface(
        const sp<IGraphicBufferProducer>& bufferProducer,
        bool controlledByApp)
    : mGraphicBufferProducer(bufferProducer)
{
    // Initialize the ANativeWindow function pointers.
    ...
}

Surface实现分析

前面说过,Surface主要对外提供绘制所需要的缓存,其实真正提供缓存的是mGraphicBufferProducer。mGraphicBufferProducer指向一个缓存队列,在需要缓存空间时,会在缓存队列中找到一个空闲的缓存块。空闲缓存块获取后,先锁定,填充绘制的图像数据,再提交。

因此,与mGraphicBufferProducer相对应的,还有一个mGraphicBufferConsumer。缓存在提交后,要被使用,缓存的使用(消费)者(如surfaceFlinger)会保存一个mGraphicBufferConsumer的引用。当mGraphicBufferProducer提交(通知)数据时,通过mGraphicBufferConsumer获取到提交的缓存数据,进行使用(合成、显示)。

这就是一个典型的生产-消费者模式。缓存数据的生产者通过Surface(也是通过mGraphicBufferProducer)提交数据,缓存的消费者通过mGraphicBufferConsumer获取数据进行消费。

ImagerReader(android_media_ImageReader.cpp)使用Surface。

static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz,
                             jint width, jint height, jint format, jint maxImages)
{
    ....


    //创建缓存队列,一个队列,一个生产者,一个消费者
    sp<IGraphicBufferProducer> gbProducer;
    sp<IGraphicBufferConsumer> gbConsumer;
    BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);

    //消费者
    sp<CpuConsumer> consumer = new CpuConsumer(gbConsumer, maxImages,
                                               /*controlledByApp*/true);
    ...

    //ImageReader的消费者
    ctx->setCpuConsumer(consumer);

    //ImageReader的生产者,gbProducer会用来创建Surface
    ctx->setProducer(gbProducer);
    ....
}

//使用gbProducer来创建Surface
static jobject ImageReader_getSurface(JNIEnv* env, jobject thiz)
{
    ALOGV("%s: ", __FUNCTION__);

    IGraphicBufferProducer* gbp = ImageReader_getProducer(env, thiz);
    if (gbp == NULL) {
        jniThrowRuntimeException(env, "CpuConsumer is uninitialized");
        return NULL;
    }

    // Wrap the IGBP in a Java-language Surface.
    return android_view_Surface_createFromIGraphicBufferProducer(env, gbp);
}

mGraphicBufferConsumer与mGraphicBufferConsumer的实现,另外再专门分析下。

⚠️ **GitHub.com Fallback** ⚠️