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

大龍的博客

常用鏈接

統計

最新評論

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ⅴaaaaaa毛片| 激情综合色丁香一区二区| 国内精品嫩模av私拍在线观看 | 欧美天堂在线观看| 国产精品爽爽爽| 红桃视频国产精品| 99视频精品免费观看| 久久精品理论片| 亚洲精品影院在线观看| 久久狠狠婷婷| 国产精品久久午夜| 亚洲精品在线一区二区| 久久天天躁狠狠躁夜夜av| 国语自产精品视频在线看| 亚洲人精品午夜| 麻豆成人在线| 99国产精品99久久久久久粉嫩| 国产日韩欧美亚洲| 伊人色综合久久天天| 欧美一区二区三区在线| 亚洲最新视频在线| 国产精品白丝av嫩草影院| 一区二区激情视频| 99国产精品久久久久久久| 欧美激情中文字幕乱码免费| 亚洲精品乱码久久久久久黑人| 久久久久高清| 亚洲午夜91| 国产亚洲精品福利| 久久婷婷综合激情| 麻豆91精品| 亚洲午夜激情网页| 亚洲视频视频在线| 国产日韩欧美亚洲| 亚洲第一区在线| 欧美日韩国产不卡| 亚洲图片你懂的| 欧美制服丝袜第一页| 亚洲国产视频直播| 亚洲一区二区三区在线| 国产一区视频网站| 亚洲精品在线免费观看视频| 国产精品主播| 亚洲国产另类精品专区| 国产精品素人视频| 亚洲黄色小视频| 国外成人在线| 亚洲影视在线播放| 亚洲视频网站在线观看| 91久久精品一区二区三区| 一区二区高清在线观看| 在线成人小视频| 性娇小13――14欧美| 亚洲图色在线| 欧美电影免费观看大全| 欧美jizz19性欧美| 国产视频久久久久| 翔田千里一区二区| 香蕉成人伊视频在线观看| 欧美日韩免费在线| 亚洲国产一区二区视频| 亚洲欧洲日产国产综合网| 久久av一区二区| 久久嫩草精品久久久久| 国产午夜精品一区二区三区欧美 | 欧美精品一区三区在线观看| 欧美成人蜜桃| 9l国产精品久久久久麻豆| 免费在线观看一区二区| 免费欧美在线视频| 亚洲国产精品一区| 欧美精品一区二区久久婷婷| 一个色综合av| 久久久精品日韩欧美| 在线观看成人网| 欧美日韩免费高清| 亚洲欧洲av一区二区| 麻豆av一区二区三区久久| 亚洲激情欧美| 国产在线麻豆精品观看| 男女激情久久| 午夜精品区一区二区三| 久久亚洲国产成人| 亚洲电影在线播放| 亚洲综合色激情五月| 影音先锋日韩有码| 欧美日韩在线播放| 美国成人直播| 欧美主播一区二区三区| 亚洲日本va午夜在线影院| 欧美超级免费视 在线| 亚洲欧洲精品一区| 欧美 日韩 国产精品免费观看| 中文亚洲视频在线| 99精品欧美一区| 亚洲国产一区二区三区高清 | 亚洲三级观看| 久久精品国产综合| 久久激情视频| 久久精品人人做人人综合| 午夜精品久久久久久久99黑人| 99视频精品| 亚洲免费一级电影| 亚洲午夜久久久| 亚洲天堂成人| 午夜视频在线观看一区二区| 西西裸体人体做爰大胆久久久| 亚洲一区二区在线观看视频| 亚洲综合日韩在线| 欧美自拍偷拍午夜视频| 久久综合中文字幕| 亚洲国产精品精华液2区45| 欧美国产一区二区| 亚洲日本成人女熟在线观看| 亚洲精品国产日韩| 亚洲欧美第一页| 久久婷婷国产麻豆91天堂| 欧美精品aa| 国产亚洲一区二区三区| 亚洲人成人77777线观看| 亚洲午夜高清视频| 免费成人在线观看视频| 欧美在线免费观看视频| 欧美国产欧美综合| 99精品视频一区二区三区| 亚洲精选成人| 性欧美精品高清| 欧美成人在线免费视频| 国产精品99久久久久久久久| 午夜视黄欧洲亚洲| 欧美另类综合| 亚洲第一区在线| 午夜在线视频观看日韩17c| 欧美高清在线一区二区| 先锋资源久久| 欧美视频成人| 一区二区三区www| 亚洲国产三级在线| 久久一区二区三区av| 国产喷白浆一区二区三区| 亚洲午夜免费视频| 欧美大片在线观看| 久久久久久高潮国产精品视| 国产乱肥老妇国产一区二| 香蕉久久一区二区不卡无毒影院 | 亚洲国产清纯| 蜜臀av性久久久久蜜臀aⅴ四虎| 亚洲在线免费观看| 国产亚洲欧美另类中文| 麻豆av一区二区三区| 蜜月aⅴ免费一区二区三区| 樱桃国产成人精品视频| 欧美福利一区二区| 欧美日韩国产在线看| 亚洲欧美在线观看| 久久精品视频在线| 亚洲精品在线视频| 亚洲欧美日韩国产一区二区| 亚洲靠逼com| 欧美亚洲成人精品| 久久亚洲私人国产精品va媚药| 久久九九精品99国产精品| 亚洲国产精品久久久久| 日韩亚洲欧美中文三级| 国产一区二区三区免费不卡 | 毛片精品免费在线观看| 欧美日韩精品一区视频| 久久亚洲色图| 国产精品久久久99| 蜜臀av在线播放一区二区三区| 夜夜嗨av一区二区三区| 亚洲第一精品夜夜躁人人爽| 国产日韩欧美a| 亚洲午夜黄色| 夜久久久久久| 欧美1级日本1级| 久热爱精品视频线路一| 精品88久久久久88久久久| 久久国产精品久久久久久久久久 | 快播亚洲色图| 久久久青草婷婷精品综合日韩| 久久xxxx精品视频| 欧美一区视频在线| 国产亚洲欧美日韩美女| 午夜精品三级视频福利| 久久久水蜜桃av免费网站| 国产亚洲精品v| 蜜桃av一区二区三区| 亚洲精品国产欧美| 亚洲线精品一区二区三区八戒| 国产精品ⅴa在线观看h| 亚洲欧美欧美一区二区三区|