音視頻開發(fā) 一:創(chuàng)建EGL環(huán)境

一双絮、簡介

??EGL 是渲染 API(如 OpenGL ES)和原生窗口系統(tǒng)之間的接口。
通常來說,OpenGL 是一個操作 GPU 的 API,它通過驅(qū)動向 GPU 發(fā)送相關(guān)指令剩檀,控制圖形渲染管線狀態(tài)機的運行狀態(tài),但是當涉及到與本地窗口系統(tǒng)進行交互時旺芽,就需要這么一個中間層沪猴,且它最好是與平臺無關(guān)的。
因此 EGL 被設(shè)計出來甥绿,作為 OpenGL 和原生窗口系統(tǒng)之間的橋梁

二字币、功能

??EGL API 是獨立于 OpenGL ES 各版本標準的獨立的一套 API,其主要作用是為 OpenGL 指令 創(chuàng)建 Context 共缕、繪制目標 Surface 洗出、配置 FrameBuffer 屬性、Swap 提交繪制結(jié)果 等图谷。

??EGL 提供如下機制:
與設(shè)備原生窗口通信
查詢繪制 surface 的可用類型和配置
創(chuàng)建繪制 surface
在 OpenGL ES 或其他渲染 API 之間同步渲染
管理紋理貼圖等渲染資源

??那么在安卓中翩活,已經(jīng)提供了GLSurfaceView,當我們需要把同一個場景渲染到不同的Surface上時便贵,此時系統(tǒng)GLSurfaceView
就不能滿足需求了菠镇,所以我們需要自己創(chuàng)建EGL環(huán)境來實現(xiàn)渲染操作。

??注意:OpenGL整體是一個狀態(tài)機承璃,通過改變狀態(tài)就能改變后續(xù)的渲染方式利耍,而
EGLContext(EgL上下文)就保存有所有狀態(tài),因此可以通過共享EGLContext
來實現(xiàn)同一場景渲染到不同的Surface上盔粹。

??看下在安卓設(shè)備中創(chuàng)建Egl環(huán)境的流程

  • 1隘梨、得到Egl實例:
  • 2、得到默認的顯示設(shè)備(就是窗口)
  • 3舷嗡、初始化默認顯示設(shè)備
  • 4轴猎、設(shè)置顯示設(shè)備的屬性
  • 5、從系統(tǒng)中獲取對應屬性的配置
  • 6进萄、創(chuàng)建EglContext
  • 7捻脖、創(chuàng)建渲染的Surface
  • 8、綁定EglContext和Surface到顯示設(shè)備中
  • 9中鼠、刷新數(shù)據(jù)可婶,顯示渲染場景

??看下具體的執(zhí)行代碼

public class EglHelper {

    private EGL10 mEgl;
    private EGLDisplay mEglDisplay;
    private EGLContext mEglContext;
    private EGLSurface mEglSurface;

    public void initEgl(Surface surface, EGLContext eglContext) {

        //1、得到Egl實例
        mEgl = (EGL10) EGLContext.getEGL();

        //2兜蠕、得到默認的顯示設(shè)備(就是窗口)
        mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
        if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
            throw new RuntimeException("eglGetDisplay failed");
        }

        //3扰肌、初始化默認顯示設(shè)備
        int[] version = new int[2];
        if (!mEgl.eglInitialize(mEglDisplay, version)) {
            throw new RuntimeException("eglInitialize failed");
        }

        //4、設(shè)置顯示設(shè)備的屬性
        int[] attributes = new int[]{
                EGL10.EGL_RED_SIZE, 8,
                EGL10.EGL_GREEN_SIZE, 8,
                EGL10.EGL_BLUE_SIZE, 8,
                EGL10.EGL_ALPHA_SIZE, 8,
                EGL10.EGL_DEPTH_SIZE, 8,
                EGL10.EGL_STENCIL_SIZE, 8,
                EGL10.EGL_RENDERABLE_TYPE, 4,
                EGL10.EGL_NONE};

        int[] num_config = new int[1];
        if (!mEgl.eglChooseConfig(mEglDisplay, attributes, null, 1, num_config)) {
            throw new IllegalArgumentException("eglChooseConfig failed");
        }

        int numConfigs = num_config[0];
        if (numConfigs <= 0) {
            throw new IllegalArgumentException(
                    "No configs match configSpec");
        }

        //5熊杨、從系統(tǒng)中獲取對應屬性的配置
        EGLConfig[] configs = new EGLConfig[numConfigs];
        if (!mEgl.eglChooseConfig(mEglDisplay, attributes, configs, numConfigs,
                num_config)) {
            throw new IllegalArgumentException("eglChooseConfig#2 failed");
        }

        //6曙旭、創(chuàng)建EglContext
        if (eglContext != null) {
            mEglContext = mEgl.eglCreateContext(mEglDisplay, configs[0], eglContext, null);
        } else {
            mEglContext = mEgl.eglCreateContext(mEglDisplay, configs[0], EGL10.EGL_NO_CONTEXT, null);
        }

        //7盗舰、創(chuàng)建渲染的Surface
        mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, configs[0], surface, null);

        //8、綁定EglContext和Surface到顯示設(shè)備中
        if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
            throw new RuntimeException("eglMakeCurrent fail");
        }
    }

    /**
     * 9桂躏、刷新數(shù)據(jù)钻趋,顯示渲染場景
     **/
    public boolean swapBuffers() {
        if (mEgl != null) {
            return mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
        } else {
            throw new RuntimeException("egl is null");
        }
    }

    public EGLContext getEglContext() {
        return mEglContext;
    }

    public void destroyEgl() {
        if (mEgl != null) {
            mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
                    EGL10.EGL_NO_SURFACE,
                    EGL10.EGL_NO_CONTEXT);

            mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
            mEglSurface = null;

            mEgl.eglDestroyContext(mEglDisplay, mEglContext);
            mEglContext = null;

            mEgl.eglTerminate(mEglDisplay);
            mEglDisplay = null;
            mEgl = null;
        }
    }

}

??使用起來也比較簡單

public class MainActivity extends Activity {

    private SurfaceView surfaceView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        surfaceView = findViewById(R.id.surface_view);

        surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {

            }

            @Override
            public void surfaceChanged(final SurfaceHolder holder, int format, final int width, final int height) {

                new Thread() {
                    @Override
                    public void run() {
                        super.run();
                        EglHelper eglHelper = new EglHelper();
                        eglHelper.initEgl(holder.getSurface(), null);

                        while (true) {
                            GLES20.glViewport(0, 0, width, height);

                            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
                            GLES20.glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
                            eglHelper.swapBuffers();

                            try {
                                Thread.sleep(16);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }.start();


            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
            }
        });


    }
}

??布局就一個SurfaceView即可

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <SurfaceView
        android:id="@+id/surface_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

??看下最終的渲染效果

渲染效果圖

??嗯,很黃很有效剂习。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蛮位,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子鳞绕,更是在濱河造成了極大的恐慌失仁,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件们何,死亡現(xiàn)場離奇詭異萄焦,居然都是意外死亡,警方通過查閱死者的電腦和手機冤竹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門拂封,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鹦蠕,你說我怎么就攤上這事冒签。” “怎么了钟病?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵萧恕,是天一觀的道長。 經(jīng)常有香客問我肠阱,道長廊鸥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任辖所,我火速辦了婚禮,結(jié)果婚禮上磨德,老公的妹妹穿的比我還像新娘缘回。我一直安慰自己,他們只是感情好典挑,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布酥宴。 她就那樣靜靜地躺著,像睡著了一般您觉。 火紅的嫁衣襯著肌膚如雪拙寡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天琳水,我揣著相機與錄音肆糕,去河邊找鬼般堆。 笑死,一個胖子當著我的面吹牛诚啃,可吹牛的內(nèi)容都是我干的淮摔。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼始赎,長吁一口氣:“原來是場噩夢啊……” “哼和橙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起造垛,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤魔招,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后五辽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體办斑,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年奔脐,在試婚紗的時候發(fā)現(xiàn)自己被綠了俄周。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡髓迎,死狀恐怖峦朗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情排龄,我是刑警寧澤波势,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站橄维,受9級特大地震影響尺铣,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜争舞,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一凛忿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧竞川,春花似錦店溢、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至遭贸,卻和暖如春戈咳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工著蛙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留删铃,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓册踩,卻偏偏與公主長得像泳姐,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子暂吉,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353