当前位置:操作系统 > 安卓/Android >>

Android应用程序请求Su易做图ceFlinger服务渲染Su易做图ce的过程分析

  Android应用程序在请求Su易做图ceFlinger服务渲染一个Su易做图ce之前,首先要将该Su易做图ce作为当前活动的绘图上下文,以便可以使用OpengGL库或者其它库的API来在上面绘制UI,我们以Android系统的开机动画应用程序bootanim为例,来说明这个问题。

        从前面Android应用程序请求Su易做图ceFlinger服务创建Su易做图ce的过程分析一文可以知道,Android系统的开机动画应用程序bootanim是在BootAnimation类的成员函数readyToRun中请求Su易做图ceFlinger服务创建Su易做图ce的。这个Su易做图ce创建完成之后,就会被设置为当前活动的绘图上下文,如下所示:

[cpp] 
status_t BootAnimation::readyToRun() { 
    ...... 
 
    // create the native su易做图ce 
    sp<Su易做图ceControl> control = session()->createSu易做图ce( 
            getpid(), 0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565); 
    ...... 
 
    sp<Su易做图ce> s = control->getSu易做图ce(); 
    ...... 
 
    // initialize opengl and egl 
    const EGLint attribs[] = { 
            EGL_DEPTH_SIZE, 0, 
            EGL_NONE 
    }; 
    ...... 
 
    EGLConfig config; 
    EGLSu易做图ce su易做图ce; 
    EGLContext context; 
 
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 
 
    eglInitialize(display, 0, 0); 
    EGLUtils::selectConfigForNativeWindow(display, attribs, s.get(), &config); 
    su易做图ce = eglCreateWindowSu易做图ce(display, config, s.get(), NULL); 
    context = eglCreateContext(display, config, NULL, NULL); 
    ...... 
 
    if (eglMakeCurrent(display, su易做图ce, su易做图ce, context) == EGL_FALSE) 
        return NO_INIT; 
 
    ...... 

       BootAnimation类的成员函数readyToRun首先调用eglGetDisplay和eglInitialize函数来获得和初始化OpengGL库的默认显示屏,接着再调用EGLUtils::selectConfigForNativeWindow函数来获得前面所创建的一个Su易做图ce(由sp<Su易做图ce>指针s来描述)的配置信息。有了这些信息之后,接下来就分别调用eglCreateWindowSu易做图ce和eglCreateContext函数来创建一个适用于OpenGL库使用的绘图表面su易做图ce以及绘图上下文context,最后就可以调用eglMakeCurrent函数来将绘图表面su易做图ce和绘图上下文context设置为当前活动的绘图表面和绘图上下文,这就相当于是将前面请求Su易做图ceFlinger服务创建的一个Su易做图ce设置为当前活动的缓图上下文了。

       完成了上述操作之后,Android系统的开机动画应用程序bootanim就可以继续使用OpengGL库的其它API来在当前活动的Su易做图ce上绘制UI了,不过,通过前面Android应用程序请求Su易做图ceFlinger服务创建Su易做图ce的过程分析一文的学习,我们知道,此时Su易做图ceFlinger服务为Android应用程序创建的Su易做图ce只有UI元数据缓冲区,而没有UI数据缓冲区,即还没有图形缓冲区,换句来说,就是还没有可以用来绘制UI的载体。那么,这些用来绘制UI的图形缓冲区是什么时候创建的呢?

       从前面Android应用程序与Su易做图ceFlinger服务的关系概述和学习计划一文可以知道,每一个Su易做图ce都有一个对应的UI元数据缓冲区堆栈,这个UI元数据缓冲区堆栈是使用一个SharedBufferStack来描述的,  

每一个UI元数据缓冲区都可能对应有一个UI数据缓冲区,这个UI数据缓冲区又可以称为图形缓冲区,它使用一个GraphicBuffer对象来描述。注意,一个UI元数据缓冲区只有第一次被使用时,Android应用程序才会为它创建一个图形缓冲区,因此,我们才说每一个UI元数据缓冲区都可能对应有一个UI数据缓冲区。例如,在图1中,目前只使到了编号为1和2的UI元数据缓冲区,因此,只有它们才有对应的图形缓冲区,而编号为3、4和5的UI元数据缓冲区没有。

       Android应用程序渲染一个Su易做图ce的过程大致如下所示:

       1. 从UI元数据缓冲区堆栈中得到一个空闲的UI元数据缓冲区;

       2. 请求Su易做图ceFlinger服务为这个空闲的UI元数据缓冲区分配一个图形缓冲区;

       3. 在图形缓冲区上面绘制好UI之后,即填充好UI数据之后,就将前面得到的空闲UI元数据缓冲区添加到UI元数据缓冲区堆栈中的待渲染队列中去;

       4. 请求Su易做图ceFlinger服务渲染前面已经准备好了图形缓冲区的Su易做图ce;

       5. Su易做图ceFlinger服务从即将要渲染的Su易做图ce的UI元数据缓冲区堆栈的待渲染队列中找到待渲染的UI元数据缓冲区;

       6. Su易做图ceFlinger服务得到了待渲染的UI元数据缓冲区之后,接着再找到在前面第2步为它所分配的图形缓冲区,最后就可以将这个图形缓冲区渲染到设备显示屏上去。

       这个过程的第1步、第3步和第5步涉到UI元数据缓冲区堆栈的一些出入栈操作,为了方便后面描述Android应用程序请求Su易做图ceFlinger服务渲染Su易做图ce的过程,我们首先介绍一下UI元数据缓冲区堆栈的一些出入栈操作。

       在前面Android应用程序请求Su易做图ceFlinger服务创建Su易做图ce的过程分析一文中,我们分析了用来描述UI元数据缓冲区堆栈的SharedBufferServer和SharedBufferClient类的父类SharedBufferBase,它有一个成员函数waitForCondition,用来等待一个条件得到满足,它定义在文件frameworks/base/include/private/su易做图ceflinger/SharedBufferStack.h中,如下所示:

[cpp]
class SharedBufferBase 

    ...... 
 
protected: 
    ...... 
 
    struct ConditionBase { 
        SharedBufferStack& stack; 
        inline ConditionBase(SharedBufferBase* sbc) 
            : stack(*sbc->mSharedStack) { } 
        virtual ~ConditionBase() { }; 
        virtual bool operator()() const = 0; 
        virtual const char* name() const = 0; 
    }; 
    status_t waitForCondition(const ConditionBase& condition); 
 
    ...... 
}; 
      SharedBufferBase类的成员函数waitForCondition只有一个参数condition,它的类型为ConditionBase,用来描述一个需要等待满足的条件。ConditionBase类是一个抽象类,我们需要以它来为父类,来实现一个自定义的条件,并且重写操作符号()和成员函数name。接下来,我们分析SharedBufferBase类的成员函数waitForCondition的实现,接着再分析ConditionBase类的一个子类的实现。
      SharedBufferBase类的成员函数waitForCondition实现在文件frameworks/base/libs/su易做图ceflinger_client/SharedBufferStack.cpp文件中,如下所示:

[cpp]
status_t SharedBufferBase::waitForCondition(const ConditionBase& condition) 

    const SharedBufferStack& stack( *mSharedStack ); 
    SharedClient& client( *mSharedClient ); 
    const nsecs_t TIMEOUT = s2ns(1); 
    const int identity = mIdentity; 
 
    Mutex::Autolock _l(client.lock); 
    while ((condition()==false) && 
            (stack.identity == identity) && 
        &n

补充:移动开发 , Android ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,