青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

大龍的博客

常用鏈接

統計

最新評論

android 顯示系統詳解(http://blog.sina.com.cn/s/blog_6b653d110100xhgw.html)

通過上一篇博客我們了解了,window和Viewroot的創建過程和作用,此時我們是否考慮過我們的布局文件中的view類是如何顯示的,我們 現在可知的是布局文件中的view類已經存放在Viewroot里面了,隨后的工作系統應該完成所有view類繪制,如何繪制和顯示是我們本篇博客討論的 重點

 

了解顯示系統需要從三方面入手:

(1)圖像引擎skia

(2)OpenGL ES

(3)surface

Android使用圖像引擎skia 作為其核心圖形引擎。Skia 圖形渲染引擎最初由 Skia 公司開

發,該公司于2005 年被 Google 收購。skia是作為一個第三方組件放在external目錄下面

 android <wbr />顯示系統詳解

 

     其實主要涉及到的3個庫:
     libcorecg.so  包含/skia/src/core的部分內容,比如其中的Region,Rect是在SurfaceFlinger里面計算可是區域的操作基本單位;
     libsgl.so        包含/skia/src/core|effects|images|ports|utils的部分和全部內容,這個實現了skia大部分的圖形效果,以及圖形格式的編輯

libskiagl.so   包含/skia/src/gl里面的內容,主要用來調用opengl實現部分效果。

。skia結構如圖:

     
android <wbr />顯示系統詳解

 

                           (圖片來自于網絡)

 

Skia作為android圖像引擎在處理部分,只要是C++代碼實現,作為第三方組件提供給android使用,作為組件提供的框架代碼最好提供一個很好的設計方式給編程者調用,從編程角度來考慮Skia

(1)輸入輸出明確

(2)接口封裝功能完善

 

Skia組件可以想象成圖像加工工廠,把原料加入進去,出來的是想要的產品,想要什么樣的產品可以通過接口調用來完成

如圖:

 android <wbr />顯示系統詳解

  

 

從圖可知我們給Skia傳遞一個bitmap或者device,我們傳遞的是bitmap或者device的地址,就像我們C語言的指針傳遞一樣,給定了bitmap或者device最后通過接口的加工完成圖像的繪制工作

 

Skia的功能只是完成圖像的繪制加工,至于完成后的bitmap如何放在LCD上顯示,是surface的工作。

 

Android 3D 引擎采用的是OpenGL ESOpenGL ES是一套為手持和嵌入式系統設計的3D引擎API,由Khronos公司維護,EGL 是 OpenGL ES 和底層 Native 平臺視窗系統之間的接口EGL 主要構成( Display , Context , Configuration )
    
EGL 相當作用是將OpenGL ES封裝,外部使用OpenGL ES,只要初始化EGL,通過EGL來使用OpenGL ES

Android中初始化EGL代碼:

 

ViewRoot.java (frameworks\base\core\java\android\view)   

private void initializeGLInner() {

        final EGL10 egl = (EGL10) EGLContext.getEGL();

        mEgl = egl;

 

        

       // 獲取Display,這里的Display對應的是顯示的硬件

        

        final EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);

        mEglDisplay = eglDisplay;

 

       

         //  初始化egl,完成一些初始化工作

        

        int[] version = new int[2];

        egl.eglInitialize(eglDisplay, version);

 

       

      // 選擇Config,其實就是設置一些FrameBuffer相關參數

        

        final int[] configSpec = {

                EGL10.EGL_RED_SIZE,      5,

                EGL10.EGL_GREEN_SIZE,    6,

                EGL10.EGL_BLUE_SIZE,     5,

                EGL10.EGL_DEPTH_SIZE,    0,

                EGL10.EGL_NONE

        };

        final EGLConfig[] configs = new EGLConfig[1];

        final int[] num_config = new int[1];

        egl.eglChooseConfig(eglDisplay, configSpec, configs, 1, num_config);

        final EGLConfig config = configs[0];

 

       

  // Context就代表這個狀態機,程序的主要工作就是向Context提供狀態,也從Context里獲取一些信息。一般狀態機的操作是通過命令的方式,類似的例子如opencore

        

        final EGLContext context = egl.eglCreateContext(eglDisplay, config,

                EGL10.EGL_NO_CONTEXT, null);

        mEglContext = context;

 

        

           // 獲取EGLSurface,這里的EGLSurface顯示的硬件對應的FrameBuffer

        

        final EGLSurface surface = egl.eglCreateWindowSurface(eglDisplay, config, mHolder, null);

        mEglSurface = surface;

 

       

              // 將狀態機和EGLSurface綁定

         

        egl.eglMakeCurrent(eglDisplay, surface, surface, context);

 

       

           // 獲取GL11,也就是3D引擎接口,通過接口操作3D

        

        final GL11 gl = (GL11) context.getGL();

        mGL = gl;

        mGlCanvas = new Canvas(gl);

        mUseGL = true;

    }

在應用層由三種顯示相關的view:

(1)        普通的view類

(2)        SurfaceView

(3)        GLSurfaceView 

 

通過上一篇博客了解到,這三種view類的都會通過setContentView加入到ViewRoot,由ViewRoot統一管理顯示,ViewRoot如何區分顯示的看如下代碼:

 

ViewRoot.java (frameworks\base\core\java\android\view) 

private void draw(boolean fullRedrawNeeded) {

      。。。。。。

 

       

       // 如果是  GLSurfaceView使用3D繪圖接口繪制 

      

 

        if (mUseGL) {

            if (!dirty.isEmpty()) {

                Canvas canvas = mGlCanvas;

                if (mGL != null && canvas != null) {

                    mGL.glDisable(GL_SCISSOR_TEST);

                    mGL.glClearColor(0, 0, 0, 0);

                    mGL.glClear(GL_COLOR_BUFFER_BIT);

                    mGL.glEnable(GL_SCISSOR_TEST);

 

                    mAttachInfo.mDrawingTime = SystemClock.uptimeMillis();

                    mAttachInfo.mIgnoreDirtyState = true;

                    mView.mPrivateFlags |= View.DRAWN;

 

                    int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);

                    try {

                        canvas.translate(0, -yoff);

                        if (mTranslator != null) {

                            mTranslator.translateCanvas(canvas);

                        }

                        canvas.setScreenDensity(scalingRequired

                                ? DisplayMetrics.DENSITY_DEVICE : 0);

                        mView.draw(canvas);

                        if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {

                            mView.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_DRAWING);

                        }

                    } finally {

                        canvas.restoreToCount(saveCount);

                    }

 

                    mAttachInfo.mIgnoreDirtyState = false;

 

             

                        // eglSwapBuffers,將數據送給FrameBuffer顯示

            

 

 

                    mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);

                    checkEglErrors();

。。。。。。

 

     

 // 如果是  普通的view類或者SurfaceView都是有2D接口顯示

 

      

 

 

                    Canvas canvas;

        try {

            int left = dirty.left;

            int top = dirty.top;

            int right = dirty.right;

            int bottom = dirty.bottom;

       

      // 通過surface獲取canvas

 

       

 

            canvas = surface.lockCanvas(dirty);

 

         。。。。。。

 

     // 從應用層傳入的view都放在ViewGroup里面,mView為視圖組,當調用mView是會調用dispatchDraw函數遍歷的調用視圖組中每個view的draw()

 

      

 

                    mView.draw(canvas);

                } finally {

                    mAttachInfo.mIgnoreDirtyState = false;

                    canvas.restoreToCount(saveCount);

                }

 

                if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {

                    mView.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_DRAWING);

                }

 

                if (Config.DEBUG && ViewDebug.showFps) {

                    int now = (int)SystemClock.elapsedRealtime();

                    if (sDrawTime != 0) {

                        nativeShowFPS(canvas, now - sDrawTime);

                    }

                    sDrawTime = now;

                }

 

                if (Config.DEBUG && ViewDebug.profileDrawing) {

                    EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime);

                }

            }

 

      // 用完以后釋放CanvasCanvas供多個surface使用

 

      

 

        } finally {

            surface.unlockCanvasAndPost(canvas);

        }

 

   。。。。。。

}

2D引擎,3D引擎和surface關系如圖:

 

android <wbr />顯示系統詳解

剩下的任務主要是分析surface:

 

原理 分析

讓我們首先看一android屏幕示意圖:

 android <wbr />顯示系統詳解

 

 

每一個應用程序對應一個或者多個activity,每個activity對應一個或者多個圖形界面,每個圖形界面我們稱為surface

在上面的圖中我們能看到3個surface ,一個是home 界面,還有就是紅、藍、,而兩個控件實際是home surface 里面的內容,3個surface相互重疊在一起,系統是如何解決圖層的重合,是surface系統的關鍵

 

(1)surface在android中解釋為一個顯示模塊的封裝,一個顯示模塊在android中需要一個合理的類來描述其信息,這里面和顯示相關的信 息有如下內容:在屏幕上有它要顯示的內容,大小,位置這些元素,surface類就是封裝了一個顯示模塊的這些信息,其中需要一個結構來記錄應用程序界面 的位置,大小,以及一個buffer 來記錄需要顯示的內容,所以這就是我們surface 的概念,

(2)多個surface顯示會出現重疊的作用,這里需要一個管理者來管理這些surface的重疊顯示,通過上面的博客的閱讀,我們大致可以想到 android會使用一種服務的方式去管理這些surface的顯示,并且各個surface和管理者通過binder通信的方式進行通信,在 android中起到管理者作用的是SurfaceFlinger,它把各個surface 組合(compose/merge) 成一個main Surface ,最后將Main Surface 的內容發送給FB/V4l2 Output ,這樣屏幕上就能看到我們想要的效果。

在實際中對這些Surface 進行merge 可以采用兩種方式,一種就是采用軟件的形式來merge ,還一種就是采用硬件的方式,軟件的方式就是我們的SurfaceFlinger ,而硬件的方式就是Overlay 。(Overlay的具體實現的內容將在下一篇的博客中詳細講解)

 

Surface類創建過程分析:

Surface.java (frameworks\base\core\java\android\view)  

這個文件為Surface類的實現代碼,也是我們在java層可以直接使用的代碼

構造函數代碼如下:

public Surface(SurfaceSession s,

            int pid, int display, int w, int h, int format, int flags)

        throws OutOfResourcesException {

        mCanvas = new CompatibleCanvas();

        init(s,pid,display,w,h,format,flags);

    }

  init(s,pid,display,w,h,format,flags);//為JNI層代碼在android_view_Surface.cpp中實現

 

android_view_Surface.cpp (frameworks\base\core\jni)

 

Surface java層函數和JNI層函數調用的映射表如下:

static JNINativeMethod gSurfaceMethods[] = {

    {"nativeClassInit",     "()V",  (void*)nativeClassInit },

    {"init",                "(Landroid/view/SurfaceSession;IIIIII)V",  (void*)Surface_init },

{"init",                "(Landroid/os/Parcel;)V",  (void*)Surface_initParcel },

。。。。。。

};

static void Surface_init(

        JNIEnv* env, jobject clazz,

        jobject session, jint pid, jint dpy, jint w, jint h, jint format, jint flags)

{

    if (session == NULL) {

        doThrow(env, "java/lang/NullPointerException");

        return;

    }

//獲取java層SurfaceSession變量  mClient域   

    SurfaceComposerClient* client =

            (SurfaceComposerClient*)env->GetIntField(session, sso.client);

//創建一個surface

    sp<SurfaceControl> surface(client->createSurface(pid, dpy, w, h, format, flags));

    if (surface == 0) {

        doThrow(env, OutOfResourcesException);

        return;

    }

    setSurfaceControl(env, clazz, surface);

}end

*******

SurfaceComposerClient* client =

            (SurfaceComposerClient*)env->GetIntField(session, sso.client);

這段代碼如何取得SurfaceComposerClient實例的引用,這里解釋一下首先在java層當我們調用surface的構造函數時候

  public Surface(SurfaceSession s,

            int pid, int display, int w, int h, int format, int flags)

,需要傳遞一個SurfaceSession類的引用SurfaceSession類調用如下:

SurfaceSession.java (frameworks\base\core\java\android\view)

public class SurfaceSession {

   

    public SurfaceSession() {

        init();

    }

    protected void finalize() throws Throwable {

        destroy();

    }

    private native void init();

    private native void destroy()

    private int mClient;

}

//函數映射表

static JNINativeMethod gSurfaceSessionMethods[] = {

     {"init",     "()V",  (void*)SurfaceSession_init },

     {"destroy",  "()V",  (void*)SurfaceSession_destroy },

    {"kill",     "()V",  (void*)SurfaceSession_kill },

};

static void SurfaceSession_init(JNIEnv* env, jobject clazz)

{

    sp<SurfaceComposerClient> client = new SurfaceComposerClient;

    client->incStrong(clazz);

    env->SetIntField(clazz, sso.client, (int)client.get());//將SurfaceComposerClient的C++層引用賦值給java層

}

 android <wbr />顯示系統詳解

說明:當創建一個surface時,同時創建一個SurfaceComposerClient,SurfaceComposerClient可以看做封裝 surface類,對于一個surface來說需要和服務器SurfaceFlinger通信,通信在android中需要使用proxy/stub機 制,SurfaceComposerClient類本身沒有這種機制,但是在它的內部有封裝了一些可以和服務器通信的類。

class SurfaceComposerClient : virtual public RefBase

{

。。。。。。

    sp<SurfaceControl> createSurface(

            int pid,            // pid of the process the surface is for

            DisplayID display,  // Display to create this surface on

            uint32_t w,         // width in pixel

            uint32_t h,         // height in pixel

            PixelFormat format, // pixel-format desired

 。。。。。

                // after assignment

                status_t                    mStatus;

                SharedClient*               mControl;

                sp<IMemoryHeap>             mControlMemory;

                sp<ISurfaceFlingerClient>   mClient; //客戶端class BClient : public BnSurfaceFlingerClient的 proxy

                sp<ISurfaceComposer>        mSignalServer; //客戶端class SurfaceFlinger : public BnSurfaceComposer 的proxy

 

};

 

}; // namespace android

 

 

 android <wbr />顯示系統詳解

當上圖關心建立完成后如下的函數會被調用:

sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,

        ISurfaceFlingerClient::surface_data_t* params,

        DisplayID d, uint32_t w, uint32_t h, PixelFormat format,

        uint32_t flags)

{

  。。。。。。

 

    switch (flags & eFXSurfaceMask) {

        case eFXSurfaceNormal:

            if (UNLIKELY(flags & ePushBuffers)) {

                layer = createPushBuffersSurfaceLocked(client, d, id,

                        w, h, flags);

            } else {

                layer = createNormalSurfaceLocked(client, d, id,

                        w, h, flags, format);

            }

            break;

        case eFXSurfaceBlur:

            layer = createBlurSurfaceLocked(client, d, id, w, h, flags);

            break;

        case eFXSurfaceDim:

            layer = createDimSurfaceLocked(client, d, id, w, h, flags);

            break;

    }

 

   。。。。。。

    }

 

    return surfaceHandle;

}

Android 提供了 4 種類型的 layer 供選擇,每個 layer 對應一種類型的窗口,并對應這種窗口相應的操作: Layer , LayerBlur , LayerBuffer , LayerDim 。

Norm Layer 是 Android 種使用最多的一種 Layer ,一般的應用程序在創建 surface 的時候都是采用的這樣的 layer ,

 Normal Layer 為每個 Surface 分配兩個 buffer : front buffer 和 back buffer ,這個前后是相對的概念,他們是可以進行替換的。 Front buffer 用于 SurfaceFlinger 進行顯示,而 Back buffer 用于應用程序進行畫圖,當 Back buffer 填滿數據 (dirty) 以后,就會 替換, back buffer 就變成了 front buffer 用于顯示,而 front buffer 就變成了 back buffer 用來畫圖,(這段話引用其他博客文章

 

sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(

        const sp<Client>& client, DisplayID display,

        int32_t id, uint32_t w, uint32_t h, uint32_t flags,

        PixelFormat& format)

{

    // initialize the surfaces

    switch (format) { // TODO: take h/w into account

    case PIXEL_FORMAT_TRANSPARENT:

    case PIXEL_FORMAT_TRANSLUCENT:

        format = PIXEL_FORMAT_RGBA_8888;

        break;

    case PIXEL_FORMAT_OPAQUE:

        format = PIXEL_FORMAT_RGB_565;

        break;

    }

 

    sp<Layer> layer = new Layer(this, display, client, id); //創建Layer

    status_t err = layer->setBuffers(w, h, format, flags);

    if (LIKELY(err == NO_ERROR)) {

        layer->initStates(w, h, flags);

        addLayer_l(layer);

    } else {

        LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));

        layer.clear();

    }

    return layer;

}

Layer類描述如下:

 

 

 

 





android <wbr />顯示系統詳解

待續。。。。。。

 

posted on 2013-01-14 22:37 大龍 閱讀(3084) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美成人第一页| 欧美激情中文不卡| 正在播放欧美一区| 这里只有精品视频| 国产精品国产三级国产aⅴ9色| 99在线精品免费视频九九视| 久久精品一区| 欧美一区二区网站| 一区二区三区视频观看| 西西人体一区二区| 黄色成人小视频| 欧美视频中文字幕| 免费成人在线观看视频| 亚洲午夜激情| 欧美激情精品久久久久久久变态| 午夜视频一区在线观看| 一区二区三区鲁丝不卡| 黄色成人av网站| 欧美日韩亚洲国产一区| 欧美国产激情二区三区| 久久久女女女女999久久| 亚洲免费影院| 日韩一级二级三级| 亚洲精品日韩一| 欧美一区二区日韩| 中文网丁香综合网| 亚洲一区尤物| 亚洲美洲欧洲综合国产一区| 亚洲国产综合在线| 亚洲免费电影在线观看| 亚洲成色777777在线观看影院| 欧美午夜视频在线观看| 欧美精品 日韩| 欧美~级网站不卡| 亚洲在线免费观看| 欧美性生交xxxxx久久久| 久久美女艺术照精彩视频福利播放| 亚洲免费观看高清完整版在线观看熊 | 一区二区三区国产| 影音欧美亚洲| 国语对白精品一区二区| 久久国产视频网站| 午夜精品久久久| 亚洲一区二区在线播放| 午夜精品久久久久99热蜜桃导演| 亚洲一区自拍| 久久成人羞羞网站| 久久爱www久久做| 久久综合国产精品台湾中文娱乐网| 久久综合中文色婷婷| 在线观看国产成人av片| 国产精品激情电影| 欧美搞黄网站| 国产一区二区三区久久| 极品少妇一区二区三区| 亚洲国产小视频| 亚洲一区精品在线| 99ri日韩精品视频| 亚洲激情网站免费观看| 欧美福利视频在线| 免费在线欧美黄色| 久久综合中文| 欧美精品电影在线| 亚洲国产专区校园欧美| 久久九九99视频| 久久久天天操| 亚洲国产精品成人综合| 中文国产成人精品| 欧美一区影院| 欧美精品尤物在线| 国产欧美一区二区视频| 亚洲成人资源| 午夜精品婷婷| 久久中文在线| 亚洲精品一线二线三线无人区| 亚洲一二三区视频在线观看| 亚洲欧美日韩另类| 男人天堂欧美日韩| 国产日韩欧美三级| 亚洲精品在线免费观看视频| 亚洲一区二区三区视频播放| 欧美在线日韩在线| 亚洲国产乱码最新视频| 香蕉久久精品日日躁夜夜躁| 媚黑女一区二区| 国产精品免费久久久久久| 136国产福利精品导航网址应用| 99精品视频免费在线观看| 久久精品在线观看| 欧美a级在线| 这里只有精品视频| 男女av一区三区二区色多| 国产精品一二| 亚洲国产小视频在线观看| 亚洲福利视频二区| 久久免费视频网站| 一本久道久久综合狠狠爱| 欧美一区国产二区| 国产精品扒开腿做爽爽爽软件| 国产精品久在线观看| 亚洲国产精品女人久久久| 亚洲国产成人高清精品| 欧美在线播放一区| 99精品视频免费观看| 欧美大片免费观看在线观看网站推荐| 国产一区二区精品久久91| 欧美一区网站| 亚洲欧美日韩中文在线制服| 欧美一区二区三区播放老司机| 欧美日韩视频在线第一区| 亚洲大胆美女视频| 久久久精品tv| 中文一区二区在线观看| 欧美久久一区| 日韩午夜免费| 先锋影院在线亚洲| 国内外成人免费激情在线视频| 亚洲一二三区在线观看| 最新国产精品拍自在线播放| 久久久久九九视频| 激情久久婷婷| 久久婷婷麻豆| 久久久久久久欧美精品| 久久久www成人免费毛片麻豆| 国产欧美日韩亚州综合| 午夜精品剧场| 欧美一区亚洲| 亚洲国产综合91精品麻豆| 欧美aaaaaaaa牛牛影院| 欧美精品日韩综合在线| 一区二区三区日韩精品| 欧美成年人视频网站| 欧美一区二区观看视频| 久久精品国产91精品亚洲| 国产视频一区三区| 欧美18av| 欧美色欧美亚洲另类二区| 午夜精品福利在线| 久久福利视频导航| 亚洲精品乱码| 一本久道久久久| 国产日韩综合一区二区性色av| 久久精品综合网| 欧美在线亚洲在线| av成人免费在线| 国产在线精品二区| 亚洲大片av| 国产女主播一区| 亚洲电影免费| 国产精品久久久久永久免费观看 | 99re66热这里只有精品4| 亚洲嫩草精品久久| 欧美一区二区精品久久911| 亚洲国产精品电影在线观看| 亚洲国产精品成人综合色在线婷婷 | 久久精品在线观看| 欧美精品一卡二卡| 亚洲一区二区三区四区在线观看| 亚洲欧美第一页| 亚洲国产美国国产综合一区二区| 日韩视频亚洲视频| 国内揄拍国内精品少妇国语| 亚洲欧洲在线免费| 亚洲小说春色综合另类电影| 韩国成人理伦片免费播放| 亚洲精选91| 亚洲国产精品精华液2区45| 亚洲视频一二| 亚洲精品国产精品乱码不99按摩| 亚洲欧美国产视频| 亚洲二区在线视频| 亚洲欧美激情一区二区| 亚洲视频一起| 欧美日韩成人精品| 美女主播一区| 国产日韩精品在线观看| 日韩视频免费| 99国内精品久久| 欧美不卡视频一区| 噜噜噜久久亚洲精品国产品小说| 欧美激情女人20p| 久久久久久久一区二区三区| 看欧美日韩国产| 国产精品捆绑调教| 一区二区三区三区在线| 亚洲天天影视| 欧美日韩成人一区二区三区| 免费观看久久久4p| 激情另类综合| 欧美在线关看| 亚洲国产片色| 亚洲精品中文字幕在线观看| 久久gogo国模啪啪人体图| 久久久久国产一区二区三区| 国产精品久久久久av| 亚洲一区国产| 性欧美video另类hd性玩具| 国产精品久久久久久久久久久久 | 亚洲欧美日韩另类| 亚洲综合三区|