OpenGL ES EGL

几个相似的概念
  • OpenCV

    从图像到数据,提供图像处理和视频处理的基础算法库,还涉及一些机器学习的算法,比如人机互动,物体识别,人脸识别,动作识别,运动跟踪,运动分析,汽车安全驾驶

  • OpenGL

    从数据到图像,主要用于生成二维、三维图像,绘制合适的视觉图像给人看

  • OpenGL ES

    OpenGL的子集,删减了一些低效的操作方式,但兼容性也更差一点

  • WebGL

    基于 OpenGL ES 2.0 的 Javascript API,用于Web浏览器呈现交互式3D图形

  • Vulkan

    免费开放的、跨平台的、底层的图形 API,旨在取代OpenGL

  • DirectX

    windows平台上提升多媒体程序执行效率的API,就它不是跨平台的

OpenGL ES的使用场景
  • 图片处理。比如图片色调转换、美颜等。视频滤镜、音频滤镜.
  • 摄像头预览效果处理。比如美颜相机、恶搞相机等。
  • 视频处理。摄像头预览效果处理可以,这个自然也不在话下了。
  • 3D 游戏。比如神庙逃亡、都市赛车等。
OpenGL ES EGL

EGL 是渲染 API(如 OpenGL ES)和原生窗口系统之间的接口

不同平台有不同的EGL系统,windows上是WGL,Linux上是GLX,Apple OS上是AGL

EGL绘图步骤
  1. 获取 EGLDisplay 对象:eglGetDisplay()
  2. 初始化与 EGLDisplay 之间的连接:eglInitialize()
  3. 获取 EGLConfig 对象:eglChooseConfig()
  4. 创建 EGLContext 实例:eglCreateContext()
  5. 创建 EGLSurface 实例:eglCreateWindowSurface()
  6. 连接 EGLContext 和 EGLSurface:eglMakeCurrent()
  7. 使用 OpenGL ES API 绘制图形:gl_*()
  8. 切换 front buffer 和 back buffer 送显:eglSwapBuffer()
  9. 断开并释放与 EGLSurface 关联的 EGLContext 对象:eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  10. 删除 EGLSurface 对象:eglDestroySurface()
  11. 删除 EGLContext 对象:eglDestroyContext()
  12. 终止与 EGLDisplay 之间的连接:eglTerminate(EGLDisplay)
  13. 释放线程:eglReleaseThread()

示例代码

#include "ViceScreenDisplay.h"

namespace android {

static const char* kSystemAssets = "/system/etc/mmi/";

sp<SurfaceComposerClient> ViceScreenDisplay::session(){
    return mSession;
}


int ViceScreenDisplay::readyToshow(){
    //first ref
    mSession = new SurfaceComposerClient();
    status_t err = mSession->linkToComposerDeath(this);
    SLOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
    if (err == NO_ERROR) {
        // Load the animation content -- this can be slow (eg 200ms)
        // called before waitForSurfaceFlinger() in main() to avoid wait
        ALOGD(" mSession->linkToComposerDeath NO_ERROR");
    }

    const char* root = getenv("ANDROID_ROOT");
    String8 path(root);
    path.appendPath(kSystemAssets);
    mAssets.addAssetPath(path, NULL, false /* appAsLib */, true /* isSystemAsset */);
    ALOGD("readyToshow Assets path = %s",path.string());

    const auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds();
    ALOGD("runToshow displayIds = %d",(int)displayIds.size());

    mDisplayToken = SurfaceComposerClient::getPhysicalDisplayToken(displayIds[1]);

    if (mDisplayToken == nullptr){
        ALOGD("runToshow mDisplayToken is nullptr");
        return -1;
    }

    DisplayInfo dinfo;
    status_t status = SurfaceComposerClient::getDisplayInfo(mDisplayToken, &dinfo);
    if (status)
        return -1;

    // create the native surface
    control = session()->createSurface(String8("showAtVice"),
            dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);

    SurfaceComposerClient::Transaction t;
    layer_state_t* ls = t.getLayerState(control);
    DisplayState& ds(t.getDisplayState(mDisplayToken));

    ALOGD("runToshow layerStack %d",ds.layerStack);
    while(ds.layerStack != 4096){
        ds = t.getDisplayState(mDisplayToken);
        t.setLayerStack(control, 4096);
        t.setDisplayLayerStack(mDisplayToken,4096);
        Rect viceRect(0,0,1920,1280);
        t.setDisplayProjection(mDisplayToken,0,viceRect,viceRect);
        ALOGD("runToshow get the layerStack %d  layerstate %d",ds.layerStack,ls->layerStack);
    }

    t.setLayer(control, 0x40000000)
        .apply();
    sp<Surface> s = control->getSurface();

    // initialize opengl and egl
    const EGLint attribs[] = {
            EGL_RED_SIZE,   8,
            EGL_GREEN_SIZE, 8,
            EGL_BLUE_SIZE,  8,
            EGL_DEPTH_SIZE, 0,
            EGL_NONE
    };
    EGLint w, h;
    EGLint numConfigs;
    EGLConfig config;
    EGLSurface surface;
    EGLContext context;

    //1.获取显示设备,使用默认的渲染类型
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (display == EGL_NO_DISPLAY || eglGetError() != EGL_SUCCESS)
        ALOGD("eglGetDisplay fail");
    else
        ALOGD("eglGetDisplay success");
    //2.初始化EGL
    EGLBoolean initialize = eglInitialize(display, nullptr, nullptr);
    //3.自定义配置
    eglChooseConfig(display, attribs, &config, 1, &numConfigs);
    //5.创建窗口渲染区域,相当于创建画布,用户想要绘制的信息都要先绘制到EGLSurface上,然后通过EGLDisplay显示
    surface = eglCreateWindowSurface(display, config, s.get(), nullptr);
    //4.创建上下文对象,该对象包含了操作所需要的所有状态信息,没有该对象,OpenGL指令就没有执行的环境
    context = eglCreateContext(display, config, nullptr, nullptr);
    //获取画布的宽高
    eglQuerySurface(display, surface, EGL_WIDTH, &w);
    eglQuerySurface(display, surface, EGL_HEIGHT, &h);
    //6.将创建的surface,display,context进行绑定,连接,因为一个应用程序可能创建多个context
    if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
        return NO_INIT;

    mDisplay = display;
    mContext = context;
    mSurface = surface;
    mWidth = w;
    mHeight = h;
    mFlingerSurfaceControl = control;
    mFlingerSurface = s;
    mTargetInset = -1;

    return 0;
}

int ViceScreenDisplay::clear(){

    ALOGD("clear");
	//9.将surface,display,context解绑
    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    //11.销毁context
    eglDestroyContext(mDisplay, mContext);
    //10.销毁surface
    eglDestroySurface(mDisplay, mSurface);
    mFlingerSurface.clear();
    mFlingerSurfaceControl.clear();
    //12.终止显示
    eglTerminate(mDisplay);
    //13.释放线程
    eglReleaseThread();
    return 0;
}

int ViceScreenDisplay::runToshow(){

    initTexture(&mAndroid[0], mAssets, "fct-display.png");
    ALOGD("init texture result,mAndroid[0].w=%d, mAndroid[0].h=%d, mAndroid[0].name=%u ",mAndroid[0].w,mAndroid[0].h,mAndroid[0].name);

    // clear screen
    glShadeModel(GL_FLAT);
    glDisable(GL_DITHER);
    glDisable(GL_SCISSOR_TEST);
    glClearColor(0,0,0,1);
    glClear(GL_COLOR_BUFFER_BIT); 
    eglSwapBuffers(mDisplay, mSurface);

    glEnable(GL_TEXTURE_2D);
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    const GLint xc = (mWidth  - mAndroid[0].w) / 2;
    const GLint yc = (mHeight - mAndroid[0].h) / 2;
    const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);

    glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
            updateRect.height());

    // Blend state
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    while(1) {
       glDisable(GL_SCISSOR_TEST);
       glClear(GL_COLOR_BUFFER_BIT);
       glEnable(GL_SCISSOR_TEST);
       glDisable(GL_BLEND);
       glEnable(GL_BLEND);
       glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
       //7.绘制图形
       glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h);
       //ALOGD("drawing graphic,mDisplay:%s, mSurface:%s",mDisplay,mSurface);
       //8.将EGLSurface中的数据交换到EGLDisplay,将绘制的内容输出到屏幕进行显示
       ALOGD("   start drawing...");
       EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);
       ALOGD("   drawing result,res:%u",res);
       if (res == EGL_FALSE){
           ALOGD("   drawing false");
           break;
       } else if (res == EGL_TRUE){
           ALOGD("   drawing success");
       } else {
           ALOGD("   drawing unknown");
       }
    }
    glDeleteTextures(1, &mAndroid[0].name);
    return 0;
}

status_t ViceScreenDisplay::initTexture(Texture* texture, AssetManager& assets,
        const char* name) {
    Asset* asset = assets.open(name, Asset::ACCESS_BUFFER);
    if (asset == nullptr){
        ALOGD("initTexture NO_INIT");
        return NO_INIT;
    }
    SkBitmap bitmap;
    sk_sp<SkData> data = SkData::MakeWithoutCopy(asset->getBuffer(false),
            asset->getLength());
    sk_sp<SkImage> image = SkImage::MakeFromEncoded(data);
    image->asLegacyBitmap(&bitmap, SkImage::kRO_LegacyBitmapMode);
    asset->close();
    delete asset;

    const int w = bitmap.width();
    const int h = bitmap.height();
    const void* p = bitmap.getPixels();

    GLint crop[4] = { 0, h, w, -h };
    texture->w = w;
    texture->h = h;

    glGenTextures(1, &texture->name);
    glBindTexture(GL_TEXTURE_2D, texture->name);

    switch (bitmap.colorType()) {
        case kAlpha_8_SkColorType:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA,
                    GL_UNSIGNED_BYTE, p);
            break;
        case kARGB_4444_SkColorType:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
                    GL_UNSIGNED_SHORT_4_4_4_4, p);
            break;
        case kN32_SkColorType:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
                    GL_UNSIGNED_BYTE, p);
            break;
        case kRGB_565_SkColorType:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB,
                    GL_UNSIGNED_SHORT_5_6_5, p);
            break;
        default:
            break;
    }

    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    return NO_ERROR;
}

void ViceScreenDisplay::binderDied(const wp<IBinder>&)
{
    // woah, surfaceflinger died!
    ALOGD("SurfaceFlinger died, exiting...");

    // calling requestExit() is not enough here because the Surface code
    // might be blocked on a condition variable that will never be updated.
    kill( getpid(), SIGKILL );
}

ViceScreenDisplay::~ViceScreenDisplay() {

    ALOGD("~ViceScreenDisplay");
}

}
;// namespace android

猜你喜欢

转载自blog.csdn.net/u013936727/article/details/128641090