web端 子线程调用opengl es

时间:2024-10-08 16:24:45
  • #include <>
  • #include <>
  • #include <>
  • #include <>
  • #include <GLES2/gl2.h>
  • #include <>
  • //#include <emscripten/html5_webgl.h>
  • #include <emscripten/html5.h>
  • #include <emscripten/>
  • #include <>
  • #include <iostream>
  • #include <string>
  • #define SR_OK 0;
  • #define SR_FAIL 1;
  • #define Y 0
  • #define U 1
  • #define V 2
  • GLuint g_ShaderProgram;
  • GLuint g_Texture2D[3];
  • GLuint g_vertexPosBuffer;
  • GLuint g_texturePosBuffer;
  • unsigned char* pYUVData=NULL;
  • int g_yuvLen=0;
  • int g_nFrameWidth = 704;
  • int g_nFrameHeight = 576;
  • int g_size=0;
  • const char* g_pHwd=NULL;
  • FILE *pFile = NULL;
  • /*顶点着色器代码*/
  • static const char g_pGLVS[] = ///<普通纹理渲染顶点着色器
  • {
  • "precision mediump float;"
  • "attribute vec4 position; "
  • "attribute vec4 texCoord; "
  • "varying vec4 pp; "
  • "void main() "
  • "{ "
  • " gl_Position = position; "
  • " pp = texCoord; "
  • "} "
  • };
  • /*像素着色器代码*/
  • const char* g_pGLFS = ///<YV12片段着色器
  • {
  • "precision mediump float;"
  • "varying vec4 pp; "
  • "uniform sampler2D Ytexture; "
  • "uniform sampler2D Utexture; "
  • "uniform sampler2D Vtexture; "
  • "void main() "
  • "{ "
  • " float r,g,b,y,u,v; "
  • " y=texture2D(Ytexture, ).r; "
  • " u=texture2D(Utexture, ).r; "
  • " v=texture2D(Vtexture, ).r; "
  • " y=1.1643*(y-0.0625); "
  • " u=u-0.5; "
  • " v=v-0.5; "
  • " r=y+1.5958*v; "
  • " g=y-0.39173*u-0.81290*v; "
  • " b=y+2.017*u; "
  • " gl_FragColor=vec4(r,g,b,1.0); "
  • "} "
  • };
  • const GLfloat g_Vertices[] = {
  • -1.0f, 1.0f,
  • -1.0f, -1.0f,
  • 1.0f, 1.0f,
  • 1.0f, 1.0f,
  • -1.0f, -1.0f,
  • 1.0f, -1.0f,
  • };
  • const GLfloat g_TexCoord[] = {
  • 0.0f, 0.0f,
  • 0.0f, 1.0f,
  • 1.0f, 0.0f,
  • 1.0f, 0.0f,
  • 0.0f, 1.0f,
  • 1.0f, 1.0f,
  • };
  • EM_JS(void, call_alert, (std::string hWnd), {
  • var hWin=hWnd.to_string();
  • ("EM_JS hWin:"+hWin);
  • var canvas = (hWin);
  • Module['canvas'].(canvas);
  • = hWin;
  • });
  • #ifdef __cplusplus
  • extern "C"
  • {
  • #endif
  • EMSCRIPTEN_KEEPALIVE
  • void initBuffers()
  • {
  • GLuint vertexPosBuffer;
  • glGenBuffers(1, &vertexPosBuffer);
  • glBindBuffer(GL_ARRAY_BUFFER, vertexPosBuffer);
  • glBufferData(GL_ARRAY_BUFFER, sizeof(g_Vertices), g_Vertices, GL_STATIC_DRAW);
  • GLint nPosLoc = glGetAttribLocation(g_ShaderProgram, "position");
  • glEnableVertexAttribArray(nPosLoc);
  • glVertexAttribPointer(nPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
  • glBindBuffer(GL_ARRAY_BUFFER, NULL);
  • g_vertexPosBuffer=vertexPosBuffer;
  • GLuint texturePosBuffer;
  • glGenBuffers(1, &texturePosBuffer);
  • glBindBuffer(GL_ARRAY_BUFFER, texturePosBuffer);
  • glBufferData(GL_ARRAY_BUFFER, sizeof(g_TexCoord), g_TexCoord, GL_STATIC_DRAW);
  • GLint nTexcoordLoc = glGetAttribLocation(g_ShaderProgram, "texCoord");
  • glEnableVertexAttribArray(nTexcoordLoc);
  • glVertexAttribPointer(nTexcoordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
  • glBindBuffer(GL_ARRAY_BUFFER, NULL);
  • g_texturePosBuffer=texturePosBuffer;
  • }
  • EMSCRIPTEN_KEEPALIVE
  • void initTexture()
  • {
  • glUseProgram(g_ShaderProgram);
  • GLuint nTexture2D[3]; ///<< YUV三层纹理数组
  • glGenTextures(3, nTexture2D);
  • for(int i = 0; i < 3; ++i)
  • {
  • glBindTexture(GL_TEXTURE_2D, nTexture2D[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);
  • glBindTexture(GL_TEXTURE_2D, NULL);
  • }
  • GLuint nTextureUniform[3];
  • nTextureUniform[Y] = glGetUniformLocation(g_ShaderProgram, "Ytexture");
  • nTextureUniform[U] = glGetUniformLocation(g_ShaderProgram, "Utexture");
  • nTextureUniform[V] = glGetUniformLocation(g_ShaderProgram, "Vtexture");
  • glUniform1i(nTextureUniform[Y], 0);
  • glUniform1i(nTextureUniform[U], 1);
  • glUniform1i(nTextureUniform[V], 2);
  • g_Texture2D[0]=nTexture2D[0];
  • g_Texture2D[1]=nTexture2D[1];
  • g_Texture2D[2]=nTexture2D[2];
  • glUseProgram(NULL);
  • }
  • EMSCRIPTEN_KEEPALIVE
  • GLuint initShaderProgram()
  • {
  • ///< 顶点着色器相关操作
  • GLuint nVertexShader = glCreateShader(GL_VERTEX_SHADER);
  • const GLchar* pVS = g_pGLVS;
  • GLint nVSLen = static_cast<GLint>(strlen(g_pGLVS));
  • glShaderSource(nVertexShader, 1, (const GLchar**)&pVS, &nVSLen);
  • GLint nCompileRet;
  • glCompileShader(nVertexShader);
  • glGetShaderiv(nVertexShader, GL_COMPILE_STATUS, &nCompileRet);
  • if(0 == nCompileRet)
  • {
  • return SR_FAIL;
  • }
  • ///< 片段着色器相关操作
  • GLuint nFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
  • const GLchar* pFS = g_pGLFS;
  • GLint nFSLen = static_cast<GLint>(strlen(g_pGLFS));
  • glShaderSource(nFragmentShader, 1, (const GLchar**)&pFS, &nFSLen);
  • glCompileShader(nFragmentShader);
  • glGetShaderiv(nFragmentShader, GL_COMPILE_STATUS, &nCompileRet);
  • if(0 == nCompileRet)
  • {
  • return SR_FAIL;
  • }
  • ///<program相关
  • GLuint nShaderProgram = glCreateProgram();
  • glAttachShader(nShaderProgram, nVertexShader);
  • glAttachShader(nShaderProgram, nFragmentShader);
  • glLinkProgram(nShaderProgram);
  • GLint nLinkRet;
  • glGetProgramiv(nShaderProgram, GL_LINK_STATUS, &nLinkRet);
  • if(0 == nLinkRet)
  • {
  • return SR_FAIL;
  • }
  • glUseProgram(nShaderProgram);
  • glDeleteShader(nVertexShader);
  • glDeleteShader(nFragmentShader);
  • return nShaderProgram;
  • }
  • EMSCRIPTEN_KEEPALIVE
  • void initContextGL()
  • {
  • // double dpr = emscripten_get_device_pixel_ratio();
  • // emscripten_set_element_css_size(hWindow, nWmdWidth / dpr, nWndHeight / dpr);
  • // emscripten_set_canvas_element_size(hWindow, nWmdWidth, nWndHeight);
  • // printf("create size success\n");
  • EmscriptenWebGLContextAttributes attr;
  • emscripten_webgl_init_context_attributes(&attr);
  • = EM_TRUE;
  • = 0;
  • #if MAX_WEBGL_VERSION >= 2
  • = 2;
  • #endif
  • printf("create context fallback\n");
  • = EMSCRIPTEN_WEBGL_CONTEXT_PROXY_FALLBACK;//EMSCRIPTEN_WEBGL_CONTEXT_PROXY_FALLBACK
  • = EM_TRUE;
  • EMSCRIPTEN_WEBGL_CONTEXT_HANDLE glContext = emscripten_webgl_create_context(g_pHwd, &attr);
  • assert(glContext);
  • //emscripten_set_canvas_element_size(g_pHwd, 355, 233);
  • EMSCRIPTEN_RESULT res=emscripten_webgl_make_context_current(glContext);
  • assert(res == EMSCRIPTEN_RESULT_SUCCESS);
  • assert(emscripten_webgl_get_current_context() == glContext);
  • printf("create context success 0821\n");
  • }
  • EMSCRIPTEN_KEEPALIVE
  • int RenderFrame(unsigned char* pFrameData, int nFrameWidth, int nFrameHeight,int size)
  • {
  • if(pFrameData==NULL||nFrameWidth<=0||nFrameHeight<=0)
  • {
  • return -1;
  • }
  • printf("RenderFrame: yuvbuffer:%02x,width:%d,height:%d,size:%d\n",pFrameData[0],nFrameWidth,nFrameHeight,size);
  • glClearColor(0.8f,0.8f,1.0f,1.0);
  • glClear(GL_COLOR_BUFFER_BIT);
  • glActiveTexture(GL_TEXTURE0);
  • glBindTexture(GL_TEXTURE_2D, g_Texture2D[Y]);
  • glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, nFrameWidth, nFrameHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pFrameData);
  • glActiveTexture(GL_TEXTURE1);
  • glBindTexture(GL_TEXTURE_2D,g_Texture2D[U] );
  • glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, nFrameWidth / 2, nFrameHeight / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pFrameData + nFrameWidth * nFrameHeight * 5 / 4);
  • glActiveTexture(GL_TEXTURE2);
  • glBindTexture(GL_TEXTURE_2D, g_Texture2D[V]);
  • glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, nFrameWidth / 2, nFrameHeight / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pFrameData + nFrameWidth * nFrameHeight);
  • glUseProgram(g_ShaderProgram);
  • //将所有顶点数据上传至顶点着色器的顶点缓存
  • #ifdef DRAW_FROM_CLIENT_MEMORY
  • glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 20, pos_and_color);
  • glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 20, (void*)(pos_and_color+2));
  • GLint nPosLoc = glGetAttribLocation(g_ShaderProgram, "position");
  • glVertexAttribPointer(nPosLoc, 2, GL_FLOAT, GL_FALSE, 0, g_Vertices);
  • GLint nTexcoordLoc = glGetAttribLocation(g_ShaderProgram, "texCoord");
  • glVertexAttribPointer(nTexcoordLoc, 2, GL_FLOAT, GL_FALSE, 0, g_TexCoord);
  • #else
  • glBindBuffer(GL_ARRAY_BUFFER, g_vertexPosBuffer);
  • GLint nPosLoc = glGetAttribLocation(g_ShaderProgram, "position");
  • glEnableVertexAttribArray(nPosLoc);
  • glVertexAttribPointer(nPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
  • glBindBuffer(GL_ARRAY_BUFFER, NULL);
  • glBindBuffer(GL_ARRAY_BUFFER, g_texturePosBuffer);
  • GLint nTexcoordLoc = glGetAttribLocation(g_ShaderProgram, "texCoord");
  • glEnableVertexAttribArray(nTexcoordLoc);
  • glVertexAttribPointer(nTexcoordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
  • glBindBuffer(GL_ARRAY_BUFFER, NULL);
  • #endif
  • glDrawArrays(GL_TRIANGLES, 0, 6);
  • glDisableVertexAttribArray(nPosLoc);
  • glDisableVertexAttribArray(nTexcoordLoc);
  • #define EXPLICIT_SWAP
  • #ifdef EXPLICIT_SWAP
  • printf("EXPLICIT_SWAP emscripten_webgl_commit_frame\n");
  • emscripten_webgl_commit_frame();
  • #endif
  • #ifdef REPORT_RESULT
  • printf("REPORT_RESULT\n");
  • REPORT_RESULT(0);
  • #endif
  • glUseProgram(NULL);
  • return SR_OK;
  • }
  • EMSCRIPTEN_KEEPALIVE
  • EM_BOOL requestRender(double time,void* p)
  • {
  • printf("requestRender 1 \n");
  • // while(1)
  • {
  • usleep(40*1000);
  • if(0 == fread(pYUVData, 1, g_size, pFile))
  • {
  • printf("read YUV file failed\n");
  • return 0;
  • }
  • printf("pYUVData:%02x\n",pYUVData[0]);
  • RenderFrame(pYUVData,g_nFrameWidth,g_nFrameHeight,g_size);
  • }
  • emscripten_request_animation_frame(requestRender,(void*)1);
  • return 1;
  • }
  • void request(void *)
  • {
  • printf("request\n");
  • emscripten_request_animation_frame(requestRender,(void*)1);
  • }
  • EMSCRIPTEN_KEEPALIVE
  • void* initRender(void *hWindow)
  • {
  • printf("start subThread init\n");
  • //初始化Context
  • initContextGL();
  • //初始化着色器程序
  • g_ShaderProgram=initShaderProgram();
  • //初始化buffer
  • initBuffers();
  • //初始化纹理
  • initTexture();
  • printf("init success\n");
  • printf("yuvLen:%d,g_size:%d\n",g_yuvLen,g_size);
  • if(pYUVData==NULL||g_yuvLen<g_size)
  • {
  • if(pYUVData!=NULL)
  • {
  • delete []pYUVData;
  • pYUVData=NULL;
  • }
  • pYUVData=new unsigned char[g_size];
  • if(pYUVData==NULL)
  • return NULL;
  • g_yuvLen=g_size;
  • }
  • printf("new yuv buffer success\n");
  • glClearColor(1.0f,0.0f,0.0f,1.0f);
  • glClear(GL_COLOR_BUFFER_BIT);
  • printf("glClearColor\n");
  • if(NULL != pYUVData)
  • {
  • pFile = fopen("./704_576.yuv", "rb");
  • if(NULL == pFile)
  • {
  • printf("open YUV file failed");
  • return NULL;
  • }
  • }
  • printf("glClearColor 222 \n");
  • emscripten_async_call(request,0,1);
  • return hWindow;
  • }
  • EMSCRIPTEN_KEEPALIVE
  • int InitMain(int nFrameWidth,int nFrameHeight,int size,void* hwnd) {
  • g_pHwd=(char*)hwnd;
  • g_nFrameHeight=nFrameHeight;
  • g_nFrameWidth=nFrameWidth;
  • g_yuvLen=size;
  • g_size=g_yuvLen;
  • printf("InitMain: nFrameWidth:%d,nFrameHeight:%d,size:%d,hwnd:%s\n",nFrameWidth,nFrameHeight,size,g_pHwd);
  • //get_canvas_size();
  • if (!emscripten_supports_offscreencanvas())
  • {
  • printf("Current browser does not support OffscreenCanvas. Skipping the rest of the tests.\n");
  • #ifdef REPORT_RESULT
  • REPORT_RESULT(1);
  • #endif
  • return -1;
  • }
  • pthread_attr_t attr;
  • pthread_attr_init(&attr);
  • emscripten_pthread_attr_settransferredcanvases(&attr, g_pHwd);
  • pthread_t thread;
  • printf("Creating thread.\n");
  • pthread_create(&thread, &attr, initRender, NULL);
  • pthread_detach(thread);
  • EM_ASM(noExitRuntime=true);
  • return 0;
  • }
  • #ifdef __cplusplus
  • }
  • #endif