1. 大致流程
1.1 初始化上下文环境
代码实现:
EGLCore.h
#ifndef AVGRAPHICS_EGLCORE_H
#define AVGRAPHICS_EGLCORE_H
#include <EGL/egl.h>
#include <GLES3/gl3.h>
class EGLCore {
private:
EGLDisplay mDisplay;
EGLSurface mSurface;
EGLContext mContext;
public:
EGLCore();
~EGLCore();
GLboolean buildContext(ANativeWindow *window, EGLContext sharedContext);
void swapBuffer();
void release();
bool makeCurrent();
EGLContext getCurrentContext();
EGLSurface getCurrentSurface();
};
#endif //AVGRAPHICS_EGLCORE_H
EGLCore.cpp
#include "EGLCore.h"
#include <android/log.h>
#include <android/native_window.h>
#include <EGL/eglext.h>
#define LOG_TAG "EGLCore"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
EGLCore::EGLCore() : mDisplay(EGL_NO_DISPLAY), mSurface(EGL_NO_SURFACE),
mContext(EGL_NO_CONTEXT) {
}
EGLCore::~EGLCore() {
mDisplay = EGL_NO_DISPLAY;
mSurface = EGL_NO_SURFACE;
mContext = EGL_NO_CONTEXT;
}
GLboolean EGLCore::buildContext(ANativeWindow *window, EGLContext sharedContext) {
// 与本地窗口系统通信
mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (mDisplay == EGL_NO_DISPLAY) {
LOGE("eglGetDisplay failed: %d", eglGetError());
return GL_FALSE;
}
if (sharedContext == NULL) {
sharedContext = EGL_NO_CONTEXT;
}
GLint majorVersion;
GLint minorVersion;
if (!eglInitialize(mDisplay, &majorVersion, &minorVersion)) {
LOGE("eglInitialize failed: %d", eglGetError());
return GL_FALSE;
}
EGLConfig config;
// 查找可用的 surface 配置
EGLint numConfigs = 0;
EGLint attribList[] = {
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
const EGLint surfaceAttr[] = {
EGL_WIDTH, 1,
EGL_HEIGHT,1,
EGL_NONE
};
// 让 EGL 推荐匹配的 EGLConfig
if (!eglChooseConfig(mDisplay, attribList, &config, 1, &numConfigs)) {
LOGE("eglChooseConfig failed: %d", eglGetError());
return GL_FALSE;
}
if (numConfigs < 1) {
LOGE("eglChooseConfig get configs number less than one");
return GL_FALSE;
}
// 创建渲染上下文(rendering context)
GLint contextAttribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
mContext = eglCreateContext(mDisplay, config, sharedContext, contextAttribs);
if (mContext == EGL_NO_CONTEXT) {
LOGE("eglCreateContext failed: %d", eglGetError());
return GL_FALSE;
}
EGLint format = 0;
if (!eglGetConfigAttrib(mDisplay, config, EGL_NATIVE_VISUAL_ID, &format)) {
LOGE("eglGetConfigAttrib failed: %d", eglGetError());
return GL_FALSE;
}
//离屏渲染
if (window == NULL)
{
mSurface = eglCreatePbufferSurface(mDisplay, config, surfaceAttr);
} else {
ANativeWindow_setBuffersGeometry(window, 0, 0, format);
// 创建 On-Screen 渲染区域
mSurface = eglCreateWindowSurface(mDisplay, config, window, 0);
}
if (mSurface == EGL_NO_SURFACE) {
LOGE("eglCreateWindowSurface failed: %d", eglGetError());
return GL_FALSE;
}
// 把 EGLContext 和 EGLSurface 关联起来
if (!eglMakeCurrent(mDisplay, mSurface, mSurface, mContext)) {
LOGE("eglMakeCurrent failed: %d", eglGetError());
return GL_FALSE;
}
LOGD("buildContext succeed");
return GL_TRUE;
}
void EGLCore::swapBuffer() {
eglSwapBuffers(mDisplay, mSurface);
}
void EGLCore::release() {
eglDestroySurface(mDisplay, mSurface);
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(mDisplay, mContext);
}
bool EGLCore::makeCurrent() {
return eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
}
EGLContext EGLCore::getCurrentContext() {
return mContext;
}
EGLSurface EGLCore::getCurrentSurface() {
return mSurface;
}
1.2 初始化纹理对象
void createTexture(GLuint &texId)
{
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, GL_NONE);
}
1.3 初始化着色器
//
// Created by zzh on 2018/5/11 0011.
//
#include "glutil.h"
#include <android/log.h>
#include <malloc.h>
#include <cstring>
#include <math.h>
#define LOG_TAG "glutil"
#define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
std::string *readShaderFromAsset(AAssetManager *manager, const char *fileName) {
AAssetDir *dir = AAssetManager_openDir(manager, "");
const char *file = nullptr;
std::string *result = new std::string;
while ((file = AAssetDir_getNextFileName(dir)) != nullptr) {
if (strcmp(file, fileName) == 0) {
AAsset *asset = AAssetManager_open(manager, file, AASSET_MODE_STREAMING);
char buf[1024];
int nb_read = 0;
while ((nb_read = AAsset_read(asset, buf, 1024)) > 0) {
result->append(buf, (unsigned long) nb_read);
}
AAsset_close(asset);
break;
}
}
AAssetDir_close(dir);
return result;
}
GLuint loadProgram(const char *vertexShaderStr, const char *fragmentShaderStr) {
GLuint program = glCreateProgram();
if (program == 0) {
LOGE("create program failed");
checkGLError("glCreateProgram");
return 0;
}
GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexShaderStr);
GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentShaderStr);
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
// 链接
glLinkProgram(program);
GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (!linked) {
GLint infoLen = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char *infoLog = (char *) malloc(sizeof(char) * infoLen);
glGetProgramInfoLog(program, infoLen, nullptr, infoLog);
LOGE("loadProgram failed: %s", infoLog);
free(infoLog);
}
glDeleteProgram(program);
return 0;
}
return program;
}
GLuint loadShader(GLenum type, const char *shaderSrc) {
GLuint shader = glCreateShader(type);
if (shader == 0) {
return 0;
}
// 加载 shader 源码
glShaderSource(shader, 1, &shaderSrc, nullptr);
// 编译
glCompileShader(shader);
// 检查编译状态
GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char *infoLog = (char *) malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(shader, infoLen, nullptr, infoLog);
LOGE("load %s shader failed: \n%s", type == GL_VERTEX_SHADER ? "vertex" : "fragment",
infoLog);
free(infoLog);
}
glDeleteShader(shader);
return 0;
}
return shader;
}
void checkGLError(const char *pGLOperation) {
for (GLint error = glGetError(); error; error = glGetError())
{
LOGE("GLUtils::CheckGLError GL Operation %s() glError (0x%x)\n", pGLOperation, error);
}
}
1.4 初始化显卡执行程序
GLuint loadProgram(const char *vertexShaderStr, const char *fragmentShaderStr) {
GLuint program = glCreateProgram();
if (program == 0) {
LOGE("create program failed");
checkGLError("glCreateProgram");
return 0;
}
GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexShaderStr);
GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentShaderStr);
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
// 链接
glLinkProgram(program);
GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (!linked) {
GLint infoLen = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char *infoLog = (char *) malloc(sizeof(char) * infoLen);
glGetProgramInfoLog(program, infoLen, nullptr, infoLog);
LOGE("loadProgram failed: %s", infoLog);
free(infoLog);
}
glDeleteProgram(program);
return 0;
}
return program;
}
1.5 渲染
void drawToView(GLuint currentTexId, GLfloat *cameraMatrix) {
// 启用透明
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glViewport(0, 0, mRecordWidth, mRecordHeight);
glUseProgram(mProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexOes);
glUniform1i(mTexLoc, 0);
glUniformMatrix4fv(mMatrixLoc, 1, GL_FALSE, cameraMatrix);
glEnableVertexAttribArray(ATTRIB_POSITION);
glVertexAttribPointer(ATTRIB_POSITION, VERTEX_POS_SIZE, GL_FLOAT, GL_FALSE, 0, VERTICES);
glEnableVertexAttribArray(ATTRIB_TEX_COORD);
glVertexAttribPointer(ATTRIB_TEX_COORD, TEX_COORD_POS_SIZE, GL_FLOAT, GL_FALSE, 0,
TEX_COORDS);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableVertexAttribArray(ATTRIB_POSITION);
glDisableVertexAttribArray(ATTRIB_TEX_COORD);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
1.7 释放资源
if (mProgram)
{
glDeleteProgram(mProgram);
}
if (mTexOes)
{
glDeleteTextures(1, &mTexOes);
}
if (mWindow) {
ANativeWindow_release(mWindow);
mWindow = nullptr;
}
eglDestroySurface(mDisplay, mSurface);
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(mDisplay, mContext);