#include "DisplayHandler.h"
//加入三维顶点数据 两个三角形组成正方形
const float vers[] = {
        1.0f, -1.0f, 0.0f,
        -1.0f, -1.0f, 0.0f,
        1.0f, 1.0f, 0.0f,
        -1.0f, 1.0f, 0.0f,
};
//加入材质坐标数据
const float txts[] = {
        1.0f, 0.0f,//右下
        0.0f, 0.0f,
        1.0f, 1.0f,
        0.0f, 1.0f
};
#define GET_STR(x) #x
//顶点着色器 glsl
static const char *vertexShader = GET_STR(
        attribute vec4 aPosition;//顶点坐标
        attribute vec2 aTexCoord;//材质顶点坐标
        varying vec2 vTexCoord;//输出的材质坐标 输出给片元着色器
        void main() {
            vTexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y);
            gl_Position = aPosition;//显示顶点
        }
);
//片元着色器 NV12
//
// glsl
static const char *fragYUV = GET_STR(
        precision mediump float;//精度
        varying vec2 vTexCoord;//顶点着色器传递的坐标
        uniform sampler2D yTexture;//输入材质参数(不透明灰度,单像素)
        uniform sampler2D uvTexture;//输入材质参数
        void main() {
            vec3 yuv;
            vec3 rgb;
            yuv.r = texture2D(yTexture, vTexCoord).r;
            yuv.g = texture2D(uvTexture, vTexCoord).r - 0.5;
            yuv.b = texture2D(uvTexture, vTexCoord).a - 0.5;
            rgb = mat3(1.0, 1.0, 1.0,
                       0.0, 0.39465, 2.03211,
                       1.13983, -0.5806, 0.0) * yuv;
            //输出像素颜色
            gl_FragColor = vec4(rgb, 1.0);
        }
);
DisplayHandler::DisplayHandler() {
    videoWidth = 1920;
    videoHeight = 1080;
    glProgram = 0;
    eglSurface = nullptr;
    eglContext = nullptr;
    eglDisplay = nullptr;
}
bool DisplayHandler::initEGL(EGLNativeWindowType *nwin) {
    //EGL
    //1  eglDisplay 显示
    eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (eglDisplay == EGL_NO_DISPLAY) {
        printf("get eglDisplay failed!");
        return false;
    }
    //初始化 后面两个参数是版本号
    if (EGL_TRUE != eglInitialize(eglDisplay, 0, 0)) {
        printf("eglInitialize failed!");
        return false;
    }
    //2  surface (关联原始窗口)
    //surface 配置
    //输出配置
    EGLConfig config;
    EGLint configNum;
    //输入配置
    EGLint configSpec[] = {
            EGL_RED_SIZE, 8,
            EGL_GREEN_SIZE, 8,
            EGL_BLUE_SIZE, 8,
            EGL_SURFACE_TYPE,
            EGL_WINDOW_BIT,
            EGL_NONE
    };
    if (EGL_TRUE != eglChooseConfig(eglDisplay, configSpec, &config, 1, &configNum)) {
        printf("eglChooseConfig failed!");
        return false;
    }
    //创建surface (关联原始窗口)
    eglSurface = eglCreateWindowSurface(eglDisplay, config, nwin, 0);
    if (eglSurface == EGL_NO_SURFACE) {
        printf("eglCreateWindowSurface failed!");
        return false;
    }
    //3  context 创建关联上下文
    const EGLint ctxAttr[] = {
            EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE
    };
    eglContext = eglCreateContext(eglDisplay, config, EGL_NO_CONTEXT, ctxAttr);
    if (eglContext == EGL_NO_CONTEXT) {
        printf("eglCreateContext failed!");
        return false;
    }
    //egl 关联 openGL
    if (EGL_TRUE != eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) {
        printf("eglMakeCurrent failed!");
        return false;
    }
    printf("EGL init success");
    return true;
}
void DisplayHandler::deinitEGL() {
    EGLBoolean success;
    if (eglDisplay != nullptr && eglSurface != nullptr) {
        success = eglDestroySurface(eglDisplay, eglSurface);
        if (!success) {
            printf("eglDestroySurface failure.");
        }
        eglSurface = nullptr;
    }
    if (eglDisplay != nullptr && eglContext != nullptr) {
        success = eglDestroyContext(eglDisplay, eglContext);
        if (!success) {
            printf("eglDestroyContext failure.");
        }
        eglContext = nullptr;
        success = eglTerminate(eglDisplay);
        if (!success) {
            printf("eglTerminate failure.");
        }
        eglDisplay = nullptr;
    }
    if (glProgram != 0) {
        glDeleteProgram(glProgram);
        glProgram = 0;
    }
}
//初始化着色器
GLint DisplayHandler::initShader(const char *code, GLint type) {
    GLuint shader;
    GLint compiled;
    // Create an empty shader object, which maintain the source code strings that define a shader
    shader = glCreateShader(type);
    if (shader == 0) {
        return 0;
    }
    // Replaces the source code in a shader object
    glShaderSource(shader, 1, &code, nullptr);
    // Compile the shader object
    glCompileShader(shader);
    // Check the shader object compile status
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
    if (!compiled) {
        GLint infoLen = 0;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
        if (infoLen > 1) {
            GLchar *infoLog = (GLchar *) malloc(sizeof(GLchar) * infoLen);
            glGetShaderInfoLog(shader, infoLen, nullptr, infoLog);
            printf("Error compiling shader:\n%s\n", infoLog);
            free(infoLog);
        }
        glDeleteShader(shader);
        return 0;
    }
    return shader;
}
GLuint DisplayHandler::loadProgram(const char *vShaderStr, const char *fShaderStr) {
    GLuint vertexShader;
    GLuint fragmentShader;
    GLuint programObject;
    GLint linked;
    // Load the vertex/fragment shaders
    vertexShader = initShader(vShaderStr, GL_VERTEX_SHADER);
    fragmentShader = initShader(fShaderStr, GL_FRAGMENT_SHADER);
    // Create the program object
    programObject = glCreateProgram();
    if (programObject == 0) {
        return 0;
    }
    // Attaches a shader object to a program object
    glAttachShader(programObject, vertexShader);
    glAttachShader(programObject, fragmentShader);
    // Bind vPosition to attribute 0
    glBindAttribLocation(programObject, 0, "vPosition");
    // Link the program object
    glLinkProgram(programObject);
    // Check the link status
    glGetProgramiv(programObject, GL_LINK_STATUS, &linked);
    if (!linked) {
        GLint infoLen = 0;
        glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen);
        if (infoLen > 1) {
            GLchar *infoLog = (GLchar *) malloc(sizeof(GLchar) * infoLen);
            glGetProgramInfoLog(programObject, infoLen, NULL, infoLog);
            printf("Error linking program:\n%s\n", infoLog);
            free(infoLog);
        }
        glDeleteProgram(programObject);
        return GL_FALSE;
    }
    // Free no longer needed shader resources
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    return programObject;
}
GLint DisplayHandler::createProgram() {
    GLuint programObject;
    // Load the shaders and get a linked program object
    programObject = loadProgram((const char *) vertexShader,
                                (const char *) fragYUV);
    if (programObject == 0) {
        return GL_FALSE;
    }
    // Store the program object
    glProgram = programObject;
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glGenTextures(TEXTURE_NUM, mTextureID);
    for (int i = 0; i < TEXTURE_NUM; i++) {
        glBindTexture(GL_TEXTURE_2D, mTextureID[i]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    }
    //激活渲染程序
    glUseProgram(glProgram);
    //获取shader中的顶点变量
    GLuint apos = (GLuint) glGetAttribLocation(glProgram, "aPosition");
    glEnableVertexAttribArray(apos);
    //传递顶点
    /*
     * apos 传到哪
     * 每一个点有多少个数据
     * 格式
     * 是否有法线向量
     * 一个数据的偏移量
     * 12 顶点有三个值(x,y,z)float存储 每个有4个字节 每一个值的间隔是 3*4 = 12
     * ver 顶点数据
     * */
    glVertexAttribPointer(apos, 3, GL_FLOAT, GL_FALSE, 12, vers);
    GLuint atex = (GLuint) glGetAttribLocation(glProgram, "aTexCoord");
    glEnableVertexAttribArray(atex);
    glVertexAttribPointer(atex, 2, GL_FLOAT, GL_FLOAT, 8, txts);
    //设置纹理层
    glUniform1i(glGetUniformLocation(glProgram, "yTexture"), 0);//对于纹理第1层
    glUniform1i(glGetUniformLocation(glProgram, "uvTexture"), 1);//对于纹理第2层
    return 0;
}
void DisplayHandler::setVideoWH(int width, int height) {
    videoWidth = width;
    videoHeight = height;
}
int DisplayHandler::getVideoWidth() const {
    return videoWidth;
}
int DisplayHandler::getVideoHeight() const {
    return videoHeight;
}
void DisplayHandler::update(unsigned char *yuvBuf) {
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, mTextureID[0]);//绑定纹理,下面的属性针对这个纹理设置
    //设置纹理的格式和大小
    /*
     * GL_TEXTURE_2D
     * 显示细节的级别
     * 内部gpu 格式 亮度 灰度图
     * 宽
     * 高
     * 边框
     * 数据的像素格式
     * 像素的数据类型
     * 纹理数据
     * */
    glTexImage2D(GL_TEXTURE_2D,
                 0,//默认
                 GL_LUMINANCE,
                 videoWidth, videoHeight, //尺寸要是2的次方  拉伸到全屏
                 0,
                 GL_LUMINANCE,//数据的像素格式,要与上面一致
                 GL_UNSIGNED_BYTE,// 像素的数据类型
                 yuvBuf
    );
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, mTextureID[1]);
    glTexImage2D(GL_TEXTURE_2D,
                 0,//默认
                 GL_LUMINANCE_ALPHA,
                 videoWidth / 2, videoHeight / 2, //尺寸要是2的次方  拉伸到全屏
                 0,
                 GL_LUMINANCE_ALPHA,//数据的像素格式,要与上面一致
                 GL_UNSIGNED_BYTE,// 像素的数据类型
                 yuvBuf + (videoWidth * videoHeight)
    );
    //三维绘制
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);//从0顶点开始 一共4个顶点
    //窗口显示
    eglSwapBuffers(eglDisplay, eglSurface);//交换buf
}
上述代码是正确,在main函数如何调用
					最新发布