805 lines
26 KiB
C++
805 lines
26 KiB
C++
/*
|
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
//
|
|
// Created on 2022/12/20.
|
|
//
|
|
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
|
|
|
|
#include "EGLRender.h"
|
|
|
|
#include <js_native_api.h>
|
|
#include <mutex>
|
|
#include <napi/native_api.h>
|
|
#include <stdlib.h>
|
|
#include <EGL/egl.h>
|
|
#include <EGL/eglext.h>
|
|
#include <GLES3/gl3.h>
|
|
#include <stdint.h>
|
|
#include <js_native_api_types.h>
|
|
#include "native_common.h"
|
|
#include "DebugLog.h"
|
|
#include "constant/constant_shape.h"
|
|
#include "GLUtils.h"
|
|
#include "../util/NapiUtil.h"
|
|
|
|
|
|
const int PARAM_TYPE_SHADER_INDEX = 300;
|
|
|
|
const int VERTEX_POS_LOC = 0;
|
|
const int TEXTURE_POS_LOC = 1;
|
|
|
|
const int32_t STR_DEFAULT_SIZE = 1024;
|
|
EGLRender *EGLRender::sInstance = nullptr;
|
|
|
|
// 顶点坐标
|
|
const static GLfloat vVertices[] = {
|
|
-1.0f, -1.0f, 0.0f, // bottom left
|
|
1.0f, -1.0f, 0.0f, // bottom right
|
|
-1.0f, 1.0f, 0.0f, // top left
|
|
1.0f, 1.0f, 0.0f, // top right
|
|
};
|
|
|
|
// 正常纹理坐标
|
|
const static GLfloat vTexCoors[] = {
|
|
0.0f, 1.0f, // bottom left
|
|
1.0f, 1.0f, // bottom right
|
|
0.0f, 0.0f, // top left
|
|
1.0f, 0.0f, // top right
|
|
};
|
|
|
|
// fbo 纹理坐标与正常纹理方向不同(上下镜像)
|
|
const static GLfloat vFboTexCoors[] = {
|
|
0.0f, 0.0f, // bottom left
|
|
1.0f, 0.0f, // bottom right
|
|
0.0f, 1.0f, // top left
|
|
1.0f, 1.0f, // top right
|
|
};
|
|
|
|
const static GLushort indices[] = { 0, 1, 2, 1, 3, 2 };
|
|
std::mutex mtx;
|
|
|
|
EGLRender* EGLRender::GetInstance()
|
|
{
|
|
mtx.lock();
|
|
if (sInstance == nullptr) {
|
|
sInstance = new EGLRender();
|
|
}
|
|
mtx.unlock();
|
|
return sInstance;
|
|
}
|
|
|
|
napi_value EGLRender::RenderInit(napi_env env, napi_callback_info info)
|
|
{
|
|
napi_value exports;
|
|
NAPI_CALL(env, napi_create_object(env, &exports));
|
|
napi_property_descriptor desc[] = {};
|
|
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
|
|
EGLRender::GetInstance() ->Init();
|
|
return exports;
|
|
}
|
|
|
|
|
|
napi_value EGLRender::RenderSetData(napi_env env, napi_callback_info info)
|
|
{
|
|
size_t argc = 3;
|
|
napi_value args[3] = { nullptr };
|
|
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
|
|
void* buffer;
|
|
size_t bufferLength;
|
|
napi_status buffStatus = napi_get_arraybuffer_info(env, args[0], &buffer, &bufferLength);
|
|
if (buffStatus != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
|
|
uint8_t* uint8_buf = reinterpret_cast<uint8_t *>(buffer);
|
|
uint32_t width;
|
|
napi_status wStatus = napi_get_value_uint32(env, args[1], &width);
|
|
if (wStatus != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
uint32_t height;
|
|
napi_status hStatus = napi_get_value_uint32(env, args[2], &height);
|
|
if (hStatus != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
|
|
EGLRender::GetInstance() -> SetImageData(uint8_buf, width, height);
|
|
return nullptr;
|
|
}
|
|
|
|
napi_value EGLRender::RenderSetIntParams(napi_env env, napi_callback_info info)
|
|
{
|
|
LOGI("gl--> RenderSetIntParams start");
|
|
size_t argc = 2;
|
|
napi_value args[2] = { nullptr };
|
|
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
|
|
|
|
uint32_t type;
|
|
napi_status tStatus = napi_get_value_uint32(env, args[0], &type);
|
|
if (tStatus != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
uint32_t param;
|
|
napi_status pStatus = napi_get_value_uint32(env, args[1], ¶m);
|
|
if (pStatus != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
EGLRender::GetInstance() -> SetIntParams(type, param);
|
|
return nullptr;
|
|
}
|
|
|
|
napi_value EGLRender::GetPixelMapOfSurface(napi_env env, napi_callback_info info)
|
|
{
|
|
size_t argc = 4;
|
|
napi_value args[4] = { nullptr };
|
|
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
|
|
|
|
uint32_t x;
|
|
napi_status xStatus = napi_get_value_uint32(env, args[0], &x);
|
|
if (xStatus != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
|
|
uint32_t y;
|
|
napi_status yStatus = napi_get_value_uint32(env, args[1], &y);
|
|
if (yStatus != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
|
|
uint32_t surfaceWidth;
|
|
napi_status swStatus = napi_get_value_uint32(env, args[2], &surfaceWidth);
|
|
if (swStatus != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
|
|
uint32_t surfaceHeight;
|
|
napi_status shStatus = napi_get_value_uint32(env, args[3], &surfaceHeight);
|
|
if (shStatus != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
|
|
uint8_t* pixels = (uint8_t*) malloc(surfaceWidth * surfaceHeight * DEFAULT_FOUR);
|
|
|
|
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
|
glReadPixels(x, y, surfaceWidth, surfaceHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
|
|
|
NativeImageUtil::Flip(&pixels, surfaceWidth, surfaceHeight);
|
|
napi_value array;
|
|
int byte_length = surfaceWidth * surfaceHeight * DEFAULT_FOUR;
|
|
if (!NativeImageUtil::CreateArrayBuffer(env, pixels, byte_length, &array)) {
|
|
LOGI("gl--> GetPixelMapOfSurface error");
|
|
}
|
|
free(pixels);
|
|
return array;
|
|
}
|
|
|
|
napi_value EGLRender::EGLIsInit(napi_env env, napi_callback_info info)
|
|
{
|
|
napi_value isInit;
|
|
int32_t value;
|
|
if (EGLRender::GetInstance() -> m_IsGLContextReady) {
|
|
value = 1;
|
|
} else {
|
|
value = 0;
|
|
}
|
|
napi_status status = napi_create_int32(env, value, &isInit);
|
|
if (status != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
return isInit;
|
|
}
|
|
|
|
napi_value EGLRender::DestroyGlesEnv(napi_env env, napi_callback_info info)
|
|
{
|
|
EGLRender::GetInstance() -> UnInit();
|
|
return nullptr;
|
|
}
|
|
|
|
napi_value EGLRender::StartUseProgram(napi_env env, napi_callback_info info)
|
|
{
|
|
EGLRender::GetInstance() -> UseProgram();
|
|
return nullptr;
|
|
}
|
|
|
|
napi_value EGLRender::Rendering(napi_env env, napi_callback_info info)
|
|
{
|
|
// 渲染
|
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const void *)0);
|
|
glBindVertexArray(GL_NONE);
|
|
glBindTexture(GL_TEXTURE_2D, GL_NONE);
|
|
return nullptr;
|
|
}
|
|
|
|
napi_value EGLRender::setTypeArrayOfFloat(napi_env env, napi_callback_info info)
|
|
{
|
|
size_t argc = 3;
|
|
napi_value args[3] = { nullptr };
|
|
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
|
|
|
|
std::string locationContent;
|
|
NapiUtil::JsValueToString(env, args[0], STR_DEFAULT_SIZE, locationContent);
|
|
|
|
char* location = (char*)locationContent.c_str();
|
|
|
|
std::string content;
|
|
NapiUtil::JsValueToString(env, args[1], STR_DEFAULT_SIZE, content);
|
|
|
|
char* key = (char*)content.c_str();
|
|
|
|
napi_typedarray_type dataType = napi_float32_array;
|
|
void* buffer;
|
|
size_t bufferLength;
|
|
size_t byte_offset;
|
|
napi_status buffStatus = napi_get_typedarray_info(env,
|
|
args[2], &dataType, &bufferLength, &buffer, &args[2], &byte_offset);
|
|
if (buffStatus != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
|
|
float* value = reinterpret_cast<float *>(buffer);
|
|
|
|
int uniformType;
|
|
|
|
if (strcmp(key, "glUniform2fv") == 0) {
|
|
uniformType = UNIFORM_TYPE_2FV;
|
|
} else if (strcmp(key, "glUniform3fv") == 0) {
|
|
uniformType = UNIFORM_TYPE_3FV;
|
|
} else if (strcmp(key, "glUniform4fv") == 0) {
|
|
uniformType = UNIFORM_TYPE_4FV;
|
|
} else if (strcmp(key, "glUniform1fv") == 0) {
|
|
uniformType = UNIFORM_TYPE_FV;
|
|
} else if (strcmp(key, "glUniform2f") == 0) {
|
|
uniformType = UNIFORM_TYPE_2F;
|
|
}
|
|
|
|
EGLRender::GetInstance() -> GlUniformArray(location, value, uniformType);
|
|
return nullptr;
|
|
}
|
|
|
|
napi_value EGLRender::setTypeArrayOfMatrix3f(napi_env env, napi_callback_info info)
|
|
{
|
|
size_t argc = 2;
|
|
napi_value args[2] = { nullptr };
|
|
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
|
|
|
|
std::string locationContent;
|
|
NapiUtil::JsValueToString(env, args[0], STR_DEFAULT_SIZE, locationContent);
|
|
|
|
char* location = (char*)locationContent.c_str();
|
|
|
|
napi_typedarray_type dataType = napi_float32_array;
|
|
void* buffer;
|
|
size_t bufferLength;
|
|
size_t byte_offset;
|
|
napi_status buffStatus = napi_get_typedarray_info(env,
|
|
args[1], &dataType, &bufferLength, &buffer, &args[1], &byte_offset);
|
|
if (buffStatus != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
|
|
float* value = reinterpret_cast<float *>(buffer);
|
|
|
|
EGLRender::GetInstance() -> GlUniformMatrix(location, value, UNIFORM_TYPE_THREE);
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
napi_value EGLRender::setTypeArrayOfMatrix4f(napi_env env, napi_callback_info info)
|
|
{
|
|
size_t argc = 2;
|
|
napi_value args[2] = { nullptr };
|
|
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
|
|
|
|
std::string locationContent;
|
|
NapiUtil::JsValueToString(env, args[0], STR_DEFAULT_SIZE, locationContent);
|
|
|
|
char* location = (char*)locationContent.c_str();
|
|
|
|
napi_typedarray_type dataType = napi_float32_array;
|
|
void* buffer;
|
|
size_t bufferLength;
|
|
size_t byte_offset;
|
|
napi_status buffStatus = napi_get_typedarray_info(env,
|
|
args[1], &dataType, &bufferLength, &buffer, &args[1], &byte_offset);
|
|
if (buffStatus != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
|
|
float* value = reinterpret_cast<float *>(buffer);
|
|
|
|
EGLRender::GetInstance() -> GlUniformMatrix(location, value, UNIFORM_TYPE_FOUR);
|
|
return nullptr;
|
|
}
|
|
|
|
napi_value EGLRender::RenderGlUniform1i(napi_env env, napi_callback_info info)
|
|
{
|
|
// int
|
|
size_t argc = 2;
|
|
napi_value args[2] = { nullptr };
|
|
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
|
|
|
|
std::string content;
|
|
NapiUtil::JsValueToString(env, args[0], STR_DEFAULT_SIZE, content);
|
|
uint32_t value;
|
|
napi_status status = napi_get_value_uint32(env, args[1], &value);
|
|
if (status != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
EGLRender::GetInstance() -> GlUniform((char*)content.c_str(), value, UNIFORM_TYPE_ZERO);
|
|
return nullptr;
|
|
}
|
|
|
|
napi_value EGLRender::RenderGlUniform1f(napi_env env, napi_callback_info info)
|
|
{
|
|
// float
|
|
size_t argc = 2;
|
|
napi_value args[2] = { nullptr };
|
|
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
|
|
|
|
std::string content;
|
|
NapiUtil::JsValueToString(env, args[0], STR_DEFAULT_SIZE, content);
|
|
double value;
|
|
napi_status status = napi_get_value_double(env, args[1], &value);
|
|
if (status != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
EGLRender::GetInstance() -> GlUniform((char*)content.c_str(), value, UNIFORM_TYPE_ONE);
|
|
return nullptr;
|
|
}
|
|
|
|
napi_value EGLRender::RenderGlUniform2fv(napi_env env, napi_callback_info info)
|
|
{
|
|
// float 数组
|
|
size_t argc = 3;
|
|
napi_value args[3] = { nullptr };
|
|
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
|
|
|
|
std::string content;
|
|
NapiUtil::JsValueToString(env, args[0], STR_DEFAULT_SIZE, content);
|
|
|
|
double value;
|
|
napi_status status = napi_get_value_double(env, args[1], &value);
|
|
if (status != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
double value2;
|
|
napi_status status2 = napi_get_value_double(env, args[2], &value2);
|
|
if (status2 != napi_ok) {
|
|
return nullptr;
|
|
}
|
|
|
|
float vce2[2];
|
|
vce2[0] = value;
|
|
vce2[1] = value2;
|
|
EGLRender::GetInstance() -> GlUniformArray((char*)content.c_str(), vce2, UNIFORM_TYPE_2FV_SIZE);
|
|
return nullptr;
|
|
}
|
|
|
|
EGLRender::EGLRender()
|
|
{
|
|
m_ImageTextureId = GL_NONE;
|
|
m_FboTextureId = GL_NONE;
|
|
m_SamplerLoc = GL_NONE;
|
|
m_TexSizeLoc = GL_NONE;
|
|
|
|
m_FboId = GL_NONE;
|
|
m_ProgramObj = GL_NONE;
|
|
m_VertexShader = GL_NONE;
|
|
m_FragmentShader = GL_NONE;
|
|
m_eglDisplay = nullptr;
|
|
m_IsGLContextReady = false;
|
|
m_ShaderIndex = 0;
|
|
}
|
|
EGLRender::~EGLRender()
|
|
{
|
|
}
|
|
void EGLRender::TexturesInit()
|
|
{
|
|
glGenTextures(1, &m_ImageTextureId); // 生成纹理名称
|
|
glBindTexture(GL_TEXTURE_2D, m_ImageTextureId); // 允许建立一个绑定到目标纹理的有名称的纹理
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glBindTexture(GL_TEXTURE_2D, GL_NONE);
|
|
glGenTextures(1, &m_FboTextureId);
|
|
glBindTexture(GL_TEXTURE_2D, m_FboTextureId);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glBindTexture(GL_TEXTURE_2D, GL_NONE);
|
|
}
|
|
void EGLRender::Init()
|
|
{
|
|
if (CreateGlEnv() == 0) {
|
|
m_IsGLContextReady = true;
|
|
}
|
|
if (!m_IsGLContextReady) {
|
|
return;
|
|
}
|
|
EGLRender::GetInstance() -> TexturesInit();
|
|
m_ProgramObj = GLUtils::CreateProgram(vShaderStr, fShaderStr0, m_VertexShader,
|
|
m_FragmentShader);
|
|
if (!m_ProgramObj) {
|
|
GLUtils::CheckGLError("Create Program");
|
|
return;
|
|
}
|
|
glGenBuffers(DEFAULT_THREE, m_VboIds);
|
|
glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[DEFAULT_ZERO]);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vVertices), vVertices, GL_STATIC_DRAW);
|
|
glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[DEFAULT_ONE]);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vFboTexCoors), vTexCoors, GL_STATIC_DRAW);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_VboIds[DEFAULT_TWO]);
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
|
glGenVertexArrays(DEFAULT_ONE, m_VaoIds);
|
|
glBindVertexArray(m_VaoIds[DEFAULT_ZERO]);
|
|
glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[DEFAULT_ZERO]);
|
|
glEnableVertexAttribArray(VERTEX_POS_LOC);
|
|
glVertexAttribPointer(VERTEX_POS_LOC,
|
|
DEFAULT_THREE,
|
|
GL_FLOAT, GL_FALSE,
|
|
DEFAULT_THREE * sizeof(GLfloat),
|
|
(const void *)DEFAULT_ZERO);
|
|
glBindBuffer(GL_ARRAY_BUFFER, GL_NONE);
|
|
glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[DEFAULT_ONE]);
|
|
glEnableVertexAttribArray(TEXTURE_POS_LOC);
|
|
glVertexAttribPointer(TEXTURE_POS_LOC,
|
|
DEFAULT_TWO,
|
|
GL_FLOAT,
|
|
GL_FALSE,
|
|
DEFAULT_TWO * sizeof(GLfloat),
|
|
(const void *)DEFAULT_ZERO);
|
|
glBindBuffer(GL_ARRAY_BUFFER, GL_NONE);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_VboIds[DEFAULT_TWO]);
|
|
glBindVertexArray(GL_NONE);
|
|
}
|
|
|
|
int EGLRender::CreateGlEnv()
|
|
{
|
|
const EGLint confAttr[] = {
|
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
|
|
EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,
|
|
EGL_DEPTH_SIZE, 16, EGL_STENCIL_SIZE, 8, EGL_NONE
|
|
};
|
|
const EGLint ctxAttr[] = {
|
|
EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE
|
|
};
|
|
const EGLint surfaceAttr[] = {
|
|
EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE
|
|
};
|
|
EGLint eglMajVers, eglMinVers;
|
|
EGLint numConfigs;
|
|
int resultCode = 0;
|
|
do {
|
|
m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
|
if (m_eglDisplay == EGL_NO_DISPLAY) {
|
|
resultCode = -1;
|
|
break;
|
|
}
|
|
// 初始化 egl 方法
|
|
if (!eglInitialize(m_eglDisplay, &eglMajVers, &eglMinVers)) {
|
|
resultCode = -1;
|
|
break;
|
|
}
|
|
// 获取 EGLConfig 对象,确定渲染表面的配置信息
|
|
if (!eglChooseConfig(m_eglDisplay, confAttr, &m_eglConf, 1, &numConfigs)) {
|
|
resultCode = -1;
|
|
break;
|
|
}
|
|
// 创建渲染表面 EGLSurface 使用 eglCreateBufferSurface 创建屏幕外渲染区域
|
|
m_eglSurface = eglCreatePbufferSurface(m_eglDisplay, m_eglConf, surfaceAttr);
|
|
if (m_eglSurface == EGL_NO_SURFACE) {
|
|
LOGI("gl-->::CreateGlesEnv happen default error");
|
|
break;
|
|
}
|
|
// 创建渲染上下文 EGLContext
|
|
m_eglCtx = eglCreateContext(m_eglDisplay, m_eglConf, EGL_NO_CONTEXT, ctxAttr);
|
|
if (m_eglCtx == EGL_NO_CONTEXT) {
|
|
EGLint error = eglGetError();
|
|
if (error == EGL_BAD_CONFIG) {
|
|
resultCode = -1;
|
|
break;
|
|
}
|
|
}
|
|
// 绑定上下文
|
|
if (!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglCtx)) {
|
|
resultCode = -1;
|
|
break;
|
|
}
|
|
} while (false);
|
|
return resultCode;
|
|
}
|
|
|
|
void EGLRender::SetImageData(uint8_t *pData, int width, int height)
|
|
{
|
|
if (pData && m_IsGLContextReady) {
|
|
if (m_RenderImage.ppPlane[0]) {
|
|
NativeImageUtil::FreeNativeImage(&m_RenderImage);
|
|
m_RenderImage.ppPlane[0] = nullptr;
|
|
}
|
|
m_RenderImage.width = width;
|
|
m_RenderImage.height = height;
|
|
m_RenderImage.format = IMAGE_FORMAT_RGBA;
|
|
NativeImageUtil::AllocNativeImage(&m_RenderImage);
|
|
if (memcpy_s(m_RenderImage.ppPlane[0],
|
|
width * height * DEFAULT_FOUR, pData, width * height * DEFAULT_FOUR) != EOK) {
|
|
return;
|
|
}
|
|
|
|
glBindTexture(GL_TEXTURE_2D, m_ImageTextureId);
|
|
glTexImage2D(GL_TEXTURE_2D,
|
|
0,
|
|
GL_RGBA,
|
|
m_RenderImage.width,
|
|
m_RenderImage.height,
|
|
0,
|
|
GL_RGBA,
|
|
GL_UNSIGNED_BYTE,
|
|
m_RenderImage.ppPlane[0]);
|
|
glBindTexture(GL_TEXTURE_2D, GL_NONE);
|
|
|
|
if (m_FboId == GL_NONE) {
|
|
// Create FBO
|
|
glGenFramebuffers(1, &m_FboId);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, m_FboId);
|
|
glBindTexture(GL_TEXTURE_2D, m_FboTextureId);
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_FboTextureId, 0);
|
|
glTexImage2D(GL_TEXTURE_2D,
|
|
0,
|
|
GL_RGBA,
|
|
m_RenderImage.width,
|
|
m_RenderImage.height,
|
|
0,
|
|
GL_RGBA,
|
|
GL_UNSIGNED_BYTE,
|
|
nullptr);
|
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
|
LOGI("gl--> EGLRender ::SetImageData glCheckFramebufferStatus status != GL_FRAMEBUFFER_COMPLETE");
|
|
}
|
|
glBindTexture(GL_TEXTURE_2D, GL_NONE);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
|
|
}
|
|
LOGI("gl--> :: SetImageData end");
|
|
}
|
|
}
|
|
|
|
void EGLRender::SetIntParams(int paramType, int param)
|
|
{
|
|
LOGI("gl--> EGLRender::SetIntParams paramType = %{public}d,param = %{public}d", paramType, param);
|
|
switch (paramType) {
|
|
case PARAM_TYPE_SHADER_INDEX: {
|
|
if (param >= 0) {
|
|
if (m_ProgramObj) {
|
|
glDeleteProgram(m_ProgramObj);
|
|
m_ProgramObj = GL_NONE;
|
|
}
|
|
const char* vShader[1];
|
|
vShader[0] = vShaderStr;
|
|
const char* fShader[1];
|
|
switch (param) {
|
|
case SHADER_TYPE_KUWAHARA: {
|
|
fShader[0] = fShaderStr3;
|
|
break;
|
|
}
|
|
case SHADER_TYPE_SWIRL: {
|
|
fShader[0] = swirlFShaderStr;
|
|
break;
|
|
}
|
|
case SHADER_TYPE_BRIGHT: {
|
|
fShader[0] = brightFShaderStr;
|
|
break;
|
|
}
|
|
case SHADER_TYPE_CONTRAST: {
|
|
fShader[0] = contrastFShaderStr;
|
|
break;
|
|
}
|
|
case SHADER_TYPE_INVERT: {
|
|
fShader[0] = invertFShaderStr;
|
|
break;
|
|
}
|
|
case SHADER_TYPE_PIXELATION: {
|
|
fShader[0] = pixelFShaderStr;
|
|
break;
|
|
}
|
|
case SHADER_TYPE_SEPIA: {
|
|
fShader[0] = colorMatrixFShaderStr;
|
|
break;
|
|
}
|
|
case SHADER_TYPE_SKETCH: {
|
|
fShader[0] = sketchShaderStr;
|
|
vShader[0] = v3x3ShaderStr;
|
|
break;
|
|
}
|
|
case SHADER_TYPE_TOON: {
|
|
fShader[0] = toonFShaderStr;
|
|
vShader[0] = v3x3ShaderStr;
|
|
break;
|
|
}
|
|
case SHADER_TYPE_VIGNETTE: {
|
|
fShader[0] = vignetteFShaderStr;
|
|
break;
|
|
}
|
|
case SHADER_TYPE_GRAYSCALE: {
|
|
fShader[0] = grayScaleShaderStr;
|
|
break;
|
|
}
|
|
case SHADER_TYPE_BLUR: {
|
|
fShader[0] = blurShaderStr;
|
|
break;
|
|
}
|
|
default:
|
|
vShader[0] = vShaderStr;
|
|
break;
|
|
}
|
|
m_ProgramObj = GLUtils::CreateProgram(vShader[0], fShader[0], m_VertexShader,
|
|
m_FragmentShader);
|
|
if (!m_ProgramObj) {
|
|
GLUtils::CheckGLError("Create Program");
|
|
LOGI("gl--> EGLRender::SetIntParams Could not create program.");
|
|
return;
|
|
}
|
|
m_SamplerLoc = glGetUniformLocation(m_ProgramObj, "s_TextureMap");
|
|
m_TexSizeLoc = glGetUniformLocation(m_ProgramObj, "u_texSize");
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EGLRender::UseProgram()
|
|
{
|
|
if (m_ProgramObj == GL_NONE) {
|
|
return;
|
|
}
|
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
|
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
glViewport(0, 0, m_RenderImage.width, m_RenderImage.height);
|
|
|
|
// DO FBO off screen rendering
|
|
glUseProgram(m_ProgramObj);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, m_FboId);
|
|
|
|
glBindVertexArray(m_VaoIds[0]);
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, m_ImageTextureId);
|
|
glUniform1i(m_SamplerLoc, 0);
|
|
|
|
if (m_TexSizeLoc > -1) {
|
|
GLfloat size[2];
|
|
size[0] = m_RenderImage.width;
|
|
size[1] = m_RenderImage.height;
|
|
glUniform2f(m_TexSizeLoc, size[0], size[1]);
|
|
}
|
|
}
|
|
|
|
void EGLRender::GlUniform(char* location, float value, int unType)
|
|
{
|
|
GLint ll = glGetUniformLocation(m_ProgramObj, location);
|
|
switch (unType) {
|
|
case UNIFORM_TYPE_ZERO:
|
|
glUniform1i(ll, (int)value);
|
|
break;
|
|
case UNIFORM_TYPE_ONE:
|
|
glUniform1f(ll, value);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EGLRender::GlUniformArray(char* location, float* value, int unType)
|
|
{
|
|
GLint ll = glGetUniformLocation(m_ProgramObj, location);
|
|
switch (unType) {
|
|
case UNIFORM_TYPE_2FV_SIZE:
|
|
GLfloat vec2[2];
|
|
vec2[0] = value[0] * m_RenderImage.width;
|
|
vec2[1] = value[1] * m_RenderImage.height;
|
|
glUniform2fv(ll, 1, vec2);
|
|
break;
|
|
case UNIFORM_TYPE_2F:
|
|
glUniform2f(ll, value[0], value[1]);
|
|
break;
|
|
case UNIFORM_TYPE_FV:
|
|
glUniform1fv(ll, 1, value);
|
|
break;
|
|
case UNIFORM_TYPE_2FV:
|
|
glUniform2fv(ll, 1, value);
|
|
break;
|
|
case UNIFORM_TYPE_3FV:
|
|
glUniform3fv(ll, 1, value);
|
|
break;
|
|
case UNIFORM_TYPE_4FV:
|
|
glUniform4fv(ll, 1, value);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EGLRender::GlUniformMatrix(char* location, float* value, int unType)
|
|
{
|
|
GLint ll = glGetUniformLocation(m_ProgramObj, location);
|
|
switch (unType) {
|
|
case UNIFORM_TYPE_THREE:
|
|
glUniformMatrix3fv(ll, 1, false, value);
|
|
break;
|
|
case UNIFORM_TYPE_FOUR:
|
|
glUniformMatrix4fv(ll, 1, false, value);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EGLRender::UnInit()
|
|
{
|
|
if (m_ProgramObj) {
|
|
glDeleteProgram(m_ProgramObj);
|
|
m_ProgramObj = GL_NONE;
|
|
}
|
|
|
|
if (m_ImageTextureId) {
|
|
glDeleteTextures(DEFAULT_ONE, &m_ImageTextureId);
|
|
m_ImageTextureId = GL_NONE;
|
|
}
|
|
|
|
if (m_FboTextureId) {
|
|
glDeleteTextures(DEFAULT_ONE, &m_FboTextureId);
|
|
m_FboTextureId = GL_NONE;
|
|
}
|
|
|
|
if (m_VboIds[DEFAULT_ZERO]) {
|
|
glDeleteBuffers(DEFAULT_THREE, m_VboIds);
|
|
m_VboIds[DEFAULT_ZERO] = GL_NONE;
|
|
m_VboIds[DEFAULT_ONE] = GL_NONE;
|
|
m_VboIds[DEFAULT_TWO] = GL_NONE;
|
|
}
|
|
|
|
if (m_VaoIds[DEFAULT_ZERO]) {
|
|
glDeleteVertexArrays(DEFAULT_ONE, m_VaoIds);
|
|
m_VaoIds[DEFAULT_ZERO] = GL_NONE;
|
|
}
|
|
|
|
if (m_FboId) {
|
|
glDeleteFramebuffers(1, &m_FboId);
|
|
m_FboId = GL_NONE;
|
|
}
|
|
if (m_IsGLContextReady) {
|
|
DestroyGl();
|
|
m_IsGLContextReady = false;
|
|
}
|
|
}
|
|
void EGLRender::DestroyGl()
|
|
{
|
|
// 释放 EGL 环境
|
|
if (m_eglDisplay != EGL_NO_DISPLAY) {
|
|
eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
|
eglDestroyContext(m_eglDisplay, m_eglCtx);
|
|
eglDestroySurface(m_eglDisplay, m_eglSurface);
|
|
eglReleaseThread();
|
|
eglTerminate(m_eglDisplay);
|
|
}
|
|
|
|
m_eglDisplay = EGL_NO_DISPLAY;
|
|
m_eglSurface = EGL_NO_SURFACE;
|
|
m_eglCtx = EGL_NO_CONTEXT;
|
|
}
|