Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

【图形图像】Android SurfaceFlinger之NativeWindow

$
0
0

1、EGLNativeWindowType

Android的GUI构建于OpenGL ES,对于2D图形来说还可以使用Skia库(https://skia.org/)。在OpenGL ES与底层的framebuffer之间,还有一层Native介质,如NativeWindow、NativeDisplay和NativePixmap,这里讨论NativeWindow。OpenGL ES是跨平台的,为了适配不同的运行环境,需要EGL将其Native化,如下所示的eglCreateWindowSurface。

EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
                  EGLNativeWindowType win,
                  const EGLint *attrib_li

eglCreateWindowSurface中的EGLNativeWindowType就是个平台相关的类型,如下所示:

#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>

typedef HDC     EGLNativeDisplayType;
typedef HBITMAP EGLNativePixmapType;
typedef HWND    EGLNativeWindowType;

#elif defined(__WINSCW__) || defined(__SYMBIAN32__)  /* Symbian */

typedef int   EGLNativeDisplayType;
typedef void *EGLNativeWindowType;
typedef void *EGLNativePixmapType;

#elif defined(__ANDROID__) || defined(ANDROID)

#include <android/native_window.h>

struct egl_native_pixmap_t;

typedef struct ANativeWindow*           EGLNativeWindowType;
typedef struct egl_native_pixmap_t*     EGLNativePixmapType;
typedef void*                           EGLNativeDisplayType;

#elif defined(__unix__)

/* X11 (tentative)  */
#include <X11/Xlib.h>
#include <X11/Xutil.h>

typedef Display *EGLNativeDisplayType;
typedef Pixmap   EGLNativePixmapType;
typedef Window   EGLNativeWindowType;

#else
#error "Platform not recognized"
#endif

/* EGL 1.2 types, renamed for consistency in EGL 1.3 */
typedef EGLNativeDisplayType NativeDisplayType;
typedef EGLNativePixmapType  NativePixmapType;
typedef EGLNativeWindowType  NativeWindowType;

可以看出,在Android系统上,EGLNativeWindowType为指向ANativeWindow结构的指针, 如下所示:

struct ANativeWindow
{
#ifdef __cplusplus
    ANativeWindow()
        : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
    {
        common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
        common.version = sizeof(ANativeWindow);
        memset(common.reserved, 0, sizeof(common.reserved));
    }
    void incStrong(const void* id) const {
        common.incRef(const_cast<android_native_base_t*>(&common));
    }
    void decStrong(const void* id) const {
        common.decRef(const_cast<android_native_base_t*>(&common));
    }
#endif

    struct android_native_base_t common;

    uint32_t flags;
    int   minSwapInterval;
    int   maxSwapInterval;
    float xdpi;
    float ydpi;
    intptr_t    oem[4];

    int     (*setSwapInterval)(struct ANativeWindow* window,
                int interval);
    int     (*dequeueBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer** buffer);
    int     (*lockBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer* buffer);
    int     (*queueBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer* buffer);
    int     (*query)(const struct ANativeWindow* window,
                int what, int* value);
    int     (*perform)(struct ANativeWindow* window,
                int operation, ... );
    int     (*cancelBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer* buffer);

    void* reserved_proc[2];
};

2、FramebufferNativeWindow

在老式的Android版本中有个专门的FramebufferNativeWindow用来实现ANativeWindow的功能,如下所示:

class FramebufferNativeWindow 
    : public EGLNativeBase<
        ANativeWindow, 
        FramebufferNativeWindow, 
        LightRefBase<FramebufferNativeWindow> >

不过在最新的Android系统(Android 7)中,FramebufferNativeWindow已被移除,看到Android源码中有如下一条提交记录:

libui: Remove FramebufferNativeWindow
We no longer support the framebuffer device, so FramebufferNativeWindow is no longer relevant.

FramebufferNativeWindow是属于libui库的,虽被移除,但其实现逻辑值得借鉴。在FramebufferNativeWindow的构造函数中,首先打开gralloc模块,即dlopen相关的gralloc库,然后打开fb0和gpu0设备,再分配需要的buffer(用于framebuffer device),这个buffer即NativeBuffer的数据结构如下:

class NativeBuffer 
    : public EGLNativeBase<
        ANativeWindowBuffer, 
        NativeBuffer, 
        LightRefBase<NativeBuffer> >

typedef struct ANativeWindowBuffer
{
#ifdef __cplusplus
    ANativeWindowBuffer() {
        common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
        common.version = sizeof(ANativeWindowBuffer);
        memset(common.reserved, 0, sizeof(common.reserved));
    }
    void incStrong(const void* id) const {
        common.incRef(const_cast<android_native_base_t*>(&common));
    }
    void decStrong(const void* id) const {
        common.decRef(const_cast<android_native_base_t*>(&common));
    }
#endif

    struct android_native_base_t common;
    int width;
    int height;
    int stride;
    int format;
    int usage;
    void* reserved[2];
    buffer_handle_t handle;
    void* reserved_proc[8];
} ANativeWindowBuffer_t;

最后是一些属性和接口赋值操作,其中最重要的一点是多缓冲技术,至少2个buffer,可以理解为一个screen-buffer(用户直接看到的东西)和一个off-screen-buffer(即将呈现给用户的东西),这就需要所谓的swap buffer,因为在屏幕上绘制东西需要时间,而屏幕刷新有一定的帧率(fps),为了保证画面流畅,就要在off-screen-buffer准备好数据后通过swap buffer把数据发送到screen-buffer以显示。举一个例子,对于单个buffer来说,如果绘制一个画面需要10秒,而屏幕每隔1秒刷新一次,用户就会感觉很卡,前9秒看到的都是不同的且不完整的画面。在NativeWindow中有两个重要的接口dequeueBuffer和queueBuffer,EGL通过dequeueBuffer来申请一个buffer,当EGL对一块buffer渲染完成后,queueBuffer用来unlock和post buffer,其中用到了条件变量用于同步操作。

3、Surface

另一个本地窗口是Surface,针对应用程序,同样继承自ANativeWindow:

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

Surface属于libgui库的东西,承担着应用进程中的UI显示需求,其分配的内存空间不属于帧缓冲区,系统中所有应用程序绘制的图像数据由SurfaceFlinger收集。Surface有两个重要的成员变量,mGraphicBufferProducer和mSlots,前者用来获取buffer,为buffer的生产者,后者则记录这些缓冲区,NUM_BUFFER_SLOTS为64。

sp<IGraphicBufferProducer> mGraphicBufferProducer;
BufferSlot mSlots[NUM_BUFFER_SLOTS];

struct BufferSlot {
        sp<GraphicBuffer> buffer;
        Region dirtyRegion;
    };

在Surface的构造函数中同样是给其成员变量赋值,做一些初始化工作,比如说如下的dequeueBuffer:

ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;

int Surface::hook_dequeueBuffer(ANativeWindow* window,
        ANativeWindowBuffer** buffer, int* fenceFd) {
    Surface* c = getSelf(window);
    return c->dequeueBuffer(buffer, fenceFd);
}

int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
    ATRACE_CALL();
    ALOGV("Surface::dequeueBuffer");

    uint32_t reqWidth;
    uint32_t reqHeight;
    PixelFormat reqFormat;
    uint32_t reqUsage;

    {
        Mutex::Autolock lock(mMutex);

        reqWidth = mReqWidth ? mReqWidth : mUserWidth;
        reqHeight = mReqHeight ? mReqHeight : mUserHeight;

        reqFormat = mReqFormat;
        reqUsage = mReqUsage;

        if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot !=
                BufferItem::INVALID_BUFFER_SLOT) {
            sp<GraphicBuffer>& gbuf(mSlots[mSharedBufferSlot].buffer);
            if (gbuf != NULL) {
                *buffer = gbuf.get();
                *fenceFd = -1;
                return OK;
            }
        }
    } // Drop the lock so that we can still touch the Surface while blocking in IGBP::dequeueBuffer

    int buf = -1;
    sp<Fence> fence;
    nsecs_t now = systemTime();
    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
            reqWidth, reqHeight, reqFormat, reqUsage);
    mLastDequeueDuration = systemTime() - now;

    if (result < 0) {
        ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer"
                "(%d, %d, %d, %d) failed: %d", reqWidth, reqHeight, reqFormat,
                reqUsage, result);
        return result;
    }

    Mutex::Autolock lock(mMutex);

    sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);

    // this should never happen
    ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);

    if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
        freeAllBuffers();
    }

    if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
        result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
        if (result != NO_ERROR) {
            ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result);
            mGraphicBufferProducer->cancelBuffer(buf, fence);
            return result;
        }
    }

    if (fence->isValid()) {
        *fenceFd = fence->dup();
        if (*fenceFd == -1) {
            ALOGE("dequeueBuffer: error duping fence: %d", errno);
            // dup() should never fail; something is badly wrong. Soldier on
            // and hope for the best; the worst that should happen is some
            // visible corruption that lasts until the next frame.
        }
    } else {
        *fenceFd = -1;
    }

    *buffer = gbuf.get();

    if (mSharedBufferMode && mAutoRefresh) {
        mSharedBufferSlot = buf;
        mSharedBufferHasBeenQueued = false;
    } else if (mSharedBufferSlot == buf) {
        mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
        mSharedBufferHasBeenQueued = false;
    }

    return OK;
}

dequeueBuffer最终通过Surface的成员函数dequeueBuffer实现,关键操作由其成员变量mGraphicBufferProducer这个buffer生产者来完成,既然有生产者就有消费者,消费者为SurfaceFlinger(libsurfaceflinger中的东西)。Surface由SurfaceControl创建、管理,如下所示:

sp<Surface> SurfaceControl::getSurface() const
{
    Mutex::Autolock _l(mLock);
    if (mSurfaceData == 0) {
        // This surface is always consumed by SurfaceFlinger, so the
        // producerControlledByApp value doesn't matter; using false.
        mSurfaceData = new Surface(mGraphicBufferProducer, false);
    }
    return mSurfaceData;
}

SurfaceControl由Surface合成的客户端SurfaceComposerClient创建,如下所示:

sp<SurfaceControl> SurfaceComposerClient::createSurface(
        const String8& name,
        uint32_t w,
        uint32_t h,
        PixelFormat format,
        uint32_t flags)
{
    sp<SurfaceControl> sur;
    if (mStatus == NO_ERROR) {
        sp<IBinder> handle;
        sp<IGraphicBufferProducer> gbp;
        status_t err = mClient->createSurface(name, w, h, format, flags,
                &handle, &gbp);
        ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
        if (err == NO_ERROR) {
            sur = new SurfaceControl(this, handle, gbp);
        }
    }
    return sur;
}

在SurfaceComposerClient的createSurface中,通过mClient(类型为sp)来createSurface,其中有两个关键变量handle(IBinder)和gbp(IGraphicBufferProducer),mClient在onFirstRef函数中获取与SurfaceFlinger(服务端)的连接,如下代码:

void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sm(ComposerService::getComposerService());
    if (sm != 0) {
        sp<ISurfaceComposerClient> conn = sm->createConnection();
        if (conn != 0) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

这样,一个普通的Surface就与SurfaceFlinger建立了联系。由此可见,ISurfaceComposerClient是由ISurfaceComposer::createConnection生成的,在这一过程中,总共涉及了三个匿名的Binder服务,分别为ISurfaceComposer、ISurfaceComposerClient和IGraphicBufferProducer,它们是紧紧相扣的,只能按上面的顺序访问。这些匿名Binder由实名Binder即在ServiceManager中注册过的SurfaceFlinger提供,从下面的函数中可以看出:

/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
    ComposerService& instance = ComposerService::getInstance();
    Mutex::Autolock _l(instance.mLock);
    if (instance.mComposerService == NULL) {
        ComposerService::getInstance().connectLocked();
        assert(instance.mComposerService != NULL);
        ALOGD("ComposerService reconnected");
    }
    return instance.mComposerService;
}

void ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger"); // 轮询查找SurfaceFlinger服务
    while (getService(name, &mComposerService) != NO_ERROR) {
        usleep(250000);
    }
    assert(mComposerService != NULL);

    // Create the death listener.
    class DeathObserver : public IBinder::DeathRecipient {
        ComposerService& mComposerService;
        virtual void binderDied(const wp<IBinder>& who) {
            ALOGW("ComposerService remote (surfaceflinger) died [%p]",
                  who.unsafe_get());
            mComposerService.composerServiceDied();
        }
     public:
        explicit DeathObserver(ComposerService& mgr) : mComposerService(mgr) { }
    };

    mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this));
    IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver);
}

前面介绍了Android的GUI系统中两个重要的本地窗口,FramebuferNativeWindow和Surface,前者是专门为SurfaceFlinger服务的,由Gralloc提供支持,后者为应用程序服务,但也由SurfaceFlinger统一管理。

作者:iEearth 发表于2017/2/28 21:07:25 原文链接
阅读:141 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>