我是靠谱客的博主 自信冰淇淋,最近开发中收集的这篇文章主要介绍ANativeWindow,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

  1. ANativeWindow : opengl工作的绘图画布本地窗口,按标准定义好函数(下面好多代码都简化)

struct ANativeWindow
{
   .....
   
   //上层定义好函数指针,传给opengl后,opengl在必要的时候会调用相应的函数
   int      (* dequeueBuffer )( struct ANativeWindow * window ,
                struct ANativeWindowBuffer ** buffer , int * fenceFd );
   
   int      (* queueBuffer )( struct ANativeWindow * window ,
                struct ANativeWindowBuffer * buffer , int fenceFd );

   int      (* cancelBuffer )( struct ANativeWindow * window ,
                struct ANativeWindowBuffer * buffer , int fenceFd );
}

ANativeWindowBuffer:绘制的图像缓冲区
struct ANativeWindowBuffer
{
    int width ;
    int height ;
    int usage ;
     .....
   //通过这个handle就跟Gralloc模块申请的图片缓存关联起来了,可能在fb申请也能是共享内存中申请的(看他了 usage
    buffer_handle_t handle
}

fenceFd:暂时把他当作这个buffer的锁,因为缓存区需要cpu,gpu,composer共享,普通锁不管用啊。


   2. android中的本地窗口
      (1.)操作显存的,surfaceflinger服务中应用的。最总渲染到屏幕的
FramebufferNativeWindow : public ANativeObjectBase <
        ANativeWindow FramebufferNativeWindow ,
        LightRefBase < FramebufferNativeWindow > >
别看上面的这么复杂其实就是 FramebufferNativeWindow: public  ANativeWindow,看名字就是包装了fb显存了,用它直接绘制到屏幕上的
  
构造函数:
FramebufferNativeWindow :: FramebufferNativeWindow ()
    : BASE (), fbDev (0), grDev (0), mUpdateOnDemand ( false )
{
    hw_module_t const * module ;
    //打开Gralloc硬件抽象层模块
    hw_get_module ( GRALLOC_HARDWARE_MODULE_ID , & module );
    //获取抽象层中的fb设备定义,渲染到屏幕的
    f ramebuffer_open ( module , & fbDev );  
    //获取抽象层图像缓存申请设备,获取一段内存或显存的
     gralloc_open ( module , & grDev );
       
    //看一下fb支持缓冲区大小,可能有多个离屏缓冲,初始化一下这些缓冲区 
    if ( fbDev -> numFramebuffers >= MIN_NUM_FRAME_BUFFERS && fbDev -> numFramebuffers <= MAX_NUM_FRAME_BUFFERS ){
        mNumBuffers = fbDev -> numFramebuffers ;
    } else {
        mNumBuffers = MIN_NUM_FRAME_BUFFERS ;
    }   
    for ( i = 0; i < mNumBuffers ; i ++)
    {
         //  NativeBuffer : public ANativeWindowBuffer 从ANativeWindowBuffer继承
          buffers [ i ] = new   NativeBuffer ( fbDev -> width , fbDev -> height , fbDev -> format , GRALLOC_USAGE_HW_FB );
         grDev -> alloc ( grDev , fbDev -> width , fbDev -> height , fbDev -> format , GRALLOC_USAGE_HW_FB , & buffers [ i ]-> handle , & buffers [ i ]-> stride );           
    }

    //opengl需要的本地窗口定义了
    const_cast < uint32_t &>( ANativeWindow :: flags ) = fbDev -> flags ;
    const_cast < float &>( ANativeWindow :: xdpi ) = fbDev -> xdpi ;
    const_cast < float &>( ANativeWindow :: ydpi ) = fbDev -> ydpi ;
    const_cast < int &>( ANativeWindow :: minSwapInterval ) = fbDev -> minSwapInterval ;
    const_cast < int &>( ANativeWindow :: maxSwapInterval ) = fbDev -> maxSwapInterval ;
    ANativeWindow :: setSwapInterval = setSwapInterval ;
    ANativeWindow :: dequeueBuffer = dequeueBuffer ;
    ANativeWindow :: queueBuffer = queueBuffer ;
    ANativeWindow :: query = query ;
    ANativeWindow :: perform = perform ;
    ANativeWindow :: dequeueBuffer_DEPRECATED = dequeueBuffer_DEPRECATED ;
    ANativeWindow :: lockBuffer_DEPRECATED = lockBuffer_DEPRECATED ;
    ANativeWindow :: queueBuffer_DEPRECATED = queueBuffer_DEPRECATED ;
}    

int FramebufferNativeWindow :: setSwapInterval ( ANativeWindow * window , int interval )
{
    return fb -> setSwapInterval ( fb , interval );
}

//opengl要一个图像缓冲区,要后台绘制了
int FramebufferNativeWindow :: dequeueBuffer ( ANativeWindow * window ANativeWindowBuffer ** buffer , int * fenceFd )
{
    //根据一系列条件找到一个空闲的缓冲区,如果没有空闲的了,还的等待queuebuffer释放一个缓存
    int index =???
    * buffer = self -> buffers [ index ]. get ();
    * fenceFd = -1;
}

//这个buffer绘制完成,可以绘制到屏幕上了
int FramebufferNativeWindow :: queueBuffer ( ANativeWindow * window , ANativeWindowBuffer * buffer , int fenceFd )
{
    //等待其他硬件都这个buffer操作完成
    sp < Fence > fence ( new Fence ( fenceFd ));
    fence -> wait ( Fence :: TIMEOUT_NEVER );   
    //绘制到屏幕上
    fb -> post ( fb , handle );
}

egl中定义了:
typedef struct ANativeWindow *           EGLNativeWindowType ;

  (2.)app端,临时用的的ANativeWindow,最终这个buffer会间接的提交到Framebuffer那面,显示到屏幕上。
 
class  Surface : public  ANativeObjectBase < ANativeWindow , Surface , RefBase >
构造函数,跟上面的差不多吧,都先初始化ANativeWindow相关函数接口
Surface :: Surface ( const sp < IGraphicBufferProducer >& bufferProducer , bool controlledByApp )
    : mGraphicBufferProducer ( bufferProducer )
{
    ANativeWindow :: setSwapInterval   = hook_setSwapInterval ;
    ANativeWindow :: dequeueBuffer     = hook_dequeueBuffer ;
    ANativeWindow :: cancelBuffer      = hook_cancelBuffer ;
    ANativeWindow :: queueBuffer       = hook_queueBuffer ;
    ANativeWindow :: query             = hook_query ;
    ANativeWindow :: perform           = hook_perform ;

    ANativeWindow :: dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED ;
    ANativeWindow :: cancelBuffer_DEPRECATED   = hook_cancelBuffer_DEPRECATED ;
    ANativeWindow :: lockBuffer_DEPRECATED     = hook_lockBuffer_DEPRECATED ;
    ANativeWindow :: queueBuffer_DEPRECATED    = hook_queueBuffer_DEPRECATED ;
    const_cast < int &>( ANativeWindow :: minSwapInterval ) = 0;
    const_cast < int &>( ANativeWindow :: maxSwapInterval ) = 1;

    mReqWidth = 0;
    mReqHeight = 0;
    mReqFormat = 0;
    .....
}

//opengl要一个图像缓冲区,要后台绘制了  
int Surface :: dequeueBuffer ( android_native_buffer_t ** buffer , int * fenceFd ) {  
    sp < Fence > fence ;

    // producer(BufferQueue)中获取一段空闲的图像缓冲区,这个内部也是通过硬件抽象层的Gralloc申请的
    status_t result = mGraphicBufferProducer -> dequeueBuffer (& buf , & fence , mSwapIntervalZero , reqW , reqH , mReqFormat , mReqUsage );
    sp < GraphicBuffer >& gbuf ( mSlots [ buf ]. buffer );
    if (( result & IGraphicBufferProducer :: BUFFER_NEEDS_REALLOCATION ) || gbuf == 0) {
        result = mGraphicBufferProducer -> requestBuffer ( buf , & gbuf );
    }

    * fenceFd = fence -> dup ();
    * buffer = gbuf . get ();
    return OK ;
}

//这个buffer绘制完成,可以用了啊 
int Surface :: queueBuffer ( android_native_buffer_t * buffer , int fenceFd ) {

    Rect crop ;
    mCrop . intersect ( Rect ( buffer -> width , buffer -> height ), & crop );
    sp < Fence > fence ( fenceFd >= 0 ? new Fence ( fenceFd ) : Fence :: NO_FENCE );
    IGraphicBufferProducer :: QueueBufferOutput output ;
    IGraphicBufferProducer :: QueueBufferInput input ( timestamp , isAutoTimestamp ,
            crop , mScalingMode , mTransform , mSwapIntervalZero , fence );

    // producer(BufferQueue)添加一段填充好的buffer,需要渲染buffer的就看着办吧
    status_t err = mGraphicBufferProducer-> queueBuffer(i , input, &output);
    uint32_t numPendingBuffers = 0;
    output . deflate (& mDefaultWidth , & mDefaultHeight , & mTransformHint ,
            & numPendingBuffers );
    return err ;
}

mGraphicBufferProducer  (BufferQueue)入队,出队是 一个跨进程的操作,他们通过Binder通讯。
   BufferQueue是一个典型的生产消费结构,生产者加工好数据丢进来,消耗者发现有数据后马上消耗掉,这个以后再分析。

3.opengl如何使用这个ANativeWindow的呢
   android中opengl环境的搭建是由EGL帮忙完成的,opengl是一组跨进程的api,


NativeWindowType就是一个 ANativeWindow
typedef struct ANativeWindow *           EGLNativeWindowType ;
  
EGLSurface eglCreateWindowSurface EGLDisplay dpy , EGLConfig config , NativeWindowType window , const EGLint * attrib_list )
{
    //保存了加载的opengl相关的so导出接口,egl接口
    egl_connection_t * cnx = NULL ;
    egl_display_ptr dp = validate_display_connection ( dpy , cnx );

    //可以想象一下就是吧window包装成一个EGlSurface, cnx -> egl是so提供的一系类函数指针
    EGLSurface surface = cnx -> egl . eglCreateWindowSurface ( iDpy , config , window , attrib_list );
}

最后

以上就是自信冰淇淋为你收集整理的ANativeWindow的全部内容,希望文章能够帮你解决ANativeWindow所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(61)

评论列表共有 0 条评论

立即
投稿
返回
顶部