2 * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "mv_util_render_2d.h"
19 static char vs_fill[] = " \n\
21 attribute vec4 a_Vertex; \n\
22 uniform mat4 u_PMVMatrix; \n\
25 gl_Position = u_PMVMatrix * a_Vertex; \n\
28 static char fs_fill[] = " \n\
30 precision mediump float; \n\
31 uniform vec4 u_Color; \n\
35 gl_FragColor = u_Color; \n\
38 static char vs_tex[] = " \n\
39 attribute vec4 a_Vertex; \n\
40 attribute vec2 a_TexCoord; \n\
41 varying vec2 v_TexCoord; \n\
42 uniform mat4 u_PMVMatrix; \n\
46 gl_Position = u_PMVMatrix * a_Vertex; \n\
47 v_TexCoord = a_TexCoord; \n\
50 static char fs_tex[] = " \n\
51 precision mediump float; \n\
52 varying vec2 v_TexCoord; \n\
53 uniform sampler2D u_sampler; \n\
54 uniform vec4 u_Color; \n\
58 gl_FragColor = texture2D(u_sampler, v_TexCoord); \n\
59 gl_FragColor *= u_Color; \n\
62 static char fs_extex[] = " \n\
63 #extension GL_NV_EGL_stream_consumer_external: enable \n\
64 #extension GL_OES_EGL_image_external : enable \n\
65 precision mediump float; \n\
66 varying vec2 v_TexCoord; \n\
67 uniform samplerExternalOES u_sampler; \n\
68 uniform vec4 u_Color; \n\
72 gl_FragColor = texture2D(u_sampler, v_TexCoord); \n\
73 gl_FragColor *= u_Color; \n\
76 static char fs_cmap_jet[] = " \n\
77 precision mediump float; \n\
78 varying vec2 v_TexCoord; \n\
79 uniform sampler2D u_sampler; \n\
80 uniform vec4 u_Color; \n\
82 float cmap_jet_red(float x) \n\
85 return 4.0 * x - 1.5; \n\
87 return -4.0 * x + 4.5; \n\
91 float cmap_jet_green(float x) \n\
94 return 4.0 * x - 0.5; \n\
96 return -4.0 * x + 3.5; \n\
100 float cmap_jet_blue(float x) \n\
103 return 4.0 * x + 0.5; \n\
105 return -4.0 * x + 2.5; \n\
109 vec4 colormap_jet(float x) \n\
111 float r = clamp(cmap_jet_red(x), 0.0, 1.0); \n\
112 float g = clamp(cmap_jet_green(x), 0.0, 1.0); \n\
113 float b = clamp(cmap_jet_blue(x), 0.0, 1.0); \n\
114 return vec4(r, g, b, 1.0); \n\
119 vec4 src_col = texture2D(u_sampler, v_TexCoord); \n\
120 gl_FragColor = colormap_jet(src_col.r); \n\
121 gl_FragColor *= u_Color; \n\
124 static char vs_tex_yuyv[] = " \n\
125 attribute vec4 a_Vertex; \n\
126 attribute vec2 a_TexCoord; \n\
127 varying vec2 v_TexCoord; \n\
128 varying vec2 v_TexCoordPix; \n\
129 uniform mat4 u_PMVMatrix; \n\
130 uniform vec2 u_TexDim; \n\
134 gl_Position = u_PMVMatrix * a_Vertex; \n\
135 v_TexCoord = a_TexCoord; \n\
136 v_TexCoordPix = a_TexCoord * u_TexDim; \n\
139 static char fs_tex_yuyv[] = " \n\
140 precision mediump float; \n\
141 varying vec2 v_TexCoord; \n\
142 varying vec2 v_TexCoordPix; \n\
143 uniform sampler2D u_sampler; \n\
144 uniform vec4 u_Color; \n\
148 vec2 evenodd = mod(v_TexCoordPix, 2.0); \n\
150 vec4 texcol = texture2D(u_sampler, v_TexCoord); \n\
151 if (evenodd.x < 1.0) { \n\
152 yuv.r = texcol.r; /* Y */ \n\
153 yuv.g = texcol.g - 0.5; /* U */ \n\
154 yuv.b = texcol.a - 0.5; /* V */ \n\
156 yuv.r = texcol.b; /* Y */ \n\
157 yuv.g = texcol.g - 0.5; /* U */ \n\
158 yuv.b = texcol.a - 0.5; /* V */ \n\
161 rgb = mat3 ( 1, 1, 1, \n\
162 0, -0.34413, 1.772, \n\
163 1.402, -0.71414, 0) * yuv; \n\
164 gl_FragColor = vec4(rgb, 1.0); \n\
165 gl_FragColor *= u_Color; \n\
169 static char *s_shader[SHADER_NUM * 2] = { vs_fill, fs_fill, vs_tex, fs_tex, vs_tex,
170 fs_extex, vs_tex, fs_cmap_jet, vs_tex_yuyv, fs_tex_yuyv };
172 static shader_obj_t s_sobj[SHADER_NUM];
173 static int s_loc_mtx[SHADER_NUM];
174 static int s_loc_color[SHADER_NUM];
175 static int s_loc_texdim[SHADER_NUM];
177 static EGLDisplay s_dpy;
178 static EGLSurface s_sfc;
179 static EGLContext s_ctx;
181 GLuint create_2d_texture(void *imgbuf, int width, int height)
185 glGenTextures(1, &texid);
186 glBindTexture(GL_TEXTURE_2D, texid);
188 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
189 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
190 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
191 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
193 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
195 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgbuf);
200 static EGLConfig find_egl_config(int r, int g, int b, int a, int d, int s, int ms, int sfc_type, int ver)
204 EGLConfig conf = 0, *conf_array = NULL;
206 EGLint config_attribs[] = { EGL_RED_SIZE,
226 config_attribs[1] = r;
227 config_attribs[3] = g;
228 config_attribs[5] = b;
229 config_attribs[7] = a;
230 config_attribs[9] = d;
231 config_attribs[11] = s;
232 config_attribs[13] = ms;
233 config_attribs[15] = sfc_type;
238 config_attribs[17] = EGL_OPENGL_ES2_BIT;
241 LOGE("Invalid version");
245 ret = eglChooseConfig(s_dpy, config_attribs, NULL, 0, &num_conf);
246 if (ret != EGL_TRUE || num_conf == 0) {
247 LOGE("Failed to call eglChooseConfig");
251 conf_array = (EGLConfig *) calloc(num_conf, sizeof(EGLConfig));
252 if (conf_array == NULL) {
253 LOGE("EGLConfig is NULL");
257 ret = eglChooseConfig(s_dpy, config_attribs, conf_array, num_conf, &num_conf);
258 if (ret != EGL_TRUE) {
259 LOGE("Failed to call eglChooseConfig");
263 for (i = 0; i < num_conf; i++) {
264 EGLint id, rsize, gsize, bsize, asize;
266 eglGetConfigAttrib(s_dpy, conf_array[i], EGL_CONFIG_ID, &id);
267 eglGetConfigAttrib(s_dpy, conf_array[i], EGL_RED_SIZE, &rsize);
268 eglGetConfigAttrib(s_dpy, conf_array[i], EGL_GREEN_SIZE, &gsize);
269 eglGetConfigAttrib(s_dpy, conf_array[i], EGL_BLUE_SIZE, &bsize);
270 eglGetConfigAttrib(s_dpy, conf_array[i], EGL_ALPHA_SIZE, &asize);
272 if (rsize == r && gsize == g && bsize == b && asize == a) {
273 conf = conf_array[i];
279 LOGE("Index is out of range");
290 int egl_init_with_platform_window_surface(int gles_version, int depth_size, int stencil_size, int sample_num, int win_w,
293 void *native_dpy, *native_win;
297 EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
298 EGLint sfc_attr[] = { EGL_NONE };
300 native_dpy = winsys_init_native_display();
301 if ((native_dpy != EGL_DEFAULT_DISPLAY) && (native_dpy == NULL)) {
302 LOGE("native_dpy is not valid");
303 return MEDIA_VISION_ERROR_INTERNAL;
306 s_dpy = eglGetDisplay(native_dpy);
307 if (s_dpy == EGL_NO_DISPLAY) {
308 LOGE("s_dpy is EGL_NO_DISPLAY");
309 return MEDIA_VISION_ERROR_INTERNAL;
312 ret = eglInitialize(s_dpy, &major, &minor);
313 if (ret != EGL_TRUE) {
314 LOGE("Failed to initialize egl");
315 return MEDIA_VISION_ERROR_INTERNAL;
318 eglBindAPI(EGL_OPENGL_ES_API);
320 config = find_egl_config(8, 8, 8, 8, depth_size, stencil_size, sample_num, EGL_WINDOW_BIT, gles_version);
321 if (config == NULL) {
322 LOGE("Failed to find egl configuration");
323 return MEDIA_VISION_ERROR_INTERNAL;
326 native_win = winsys_init_native_window(s_dpy, win_w, win_h);
327 if (native_win == NULL) {
328 LOGE("window is NULL");
329 return MEDIA_VISION_ERROR_INTERNAL;
332 s_sfc = eglCreateWindowSurface(s_dpy, config, (NativeWindowType) native_win, sfc_attr);
333 if (s_sfc == EGL_NO_SURFACE) {
334 LOGE("s_sfc is EGL_NO_SURFACE");
335 return MEDIA_VISION_ERROR_INTERNAL;
338 switch (gles_version) {
340 context_attribs[1] = 1;
343 context_attribs[1] = 2;
346 context_attribs[1] = 3;
349 LOGE("Invalid gles version");
350 return MEDIA_VISION_ERROR_INTERNAL;
353 s_ctx = eglCreateContext(s_dpy, config, EGL_NO_CONTEXT, context_attribs);
354 if (s_ctx == EGL_NO_CONTEXT) {
355 LOGE("s_ctx is EGL_NO_CONTEXT");
356 return MEDIA_VISION_ERROR_INTERNAL;
359 ret = eglMakeCurrent(s_dpy, s_sfc, s_sfc, s_ctx);
360 if (ret != EGL_TRUE) {
361 LOGE("Falied to call eglMakeCurrent()");
362 return MEDIA_VISION_ERROR_INTERNAL;
365 return MEDIA_VISION_ERROR_NONE;
372 ret = eglSwapBuffers(s_dpy, s_sfc);
373 if (ret != EGL_TRUE) {
374 LOGE("Failed to call eglSwapBuffers()");
375 return MEDIA_VISION_ERROR_INTERNAL;
378 return MEDIA_VISION_ERROR_NONE;
381 static float varray[] = { 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0 };
383 static float tarray[] = { 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0 };
385 static float tarray2[] = { 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0 };
387 static float s_matprj[16];
388 static void set_projection_matrix(int w, int h)
391 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f
394 mat_proj[0] = 2.0f / (float) w;
395 mat_proj[5] = -2.0f / (float) h;
397 memcpy(s_matprj, mat_proj, 16 * sizeof(float));
400 int init_2d_renderer(int w, int h)
404 for (i = 0; i < SHADER_NUM; i++) {
405 if (generate_shader(&s_sobj[i], s_shader[2 * i], s_shader[2 * i + 1]) < 0) {
406 LOGE("%s(%d)", __FILE__, __LINE__);
407 return MEDIA_VISION_ERROR_INTERNAL;
410 s_loc_mtx[i] = glGetUniformLocation(s_sobj[i].program, "u_PMVMatrix");
411 s_loc_color[i] = glGetUniformLocation(s_sobj[i].program, "u_Color");
412 s_loc_texdim[i] = glGetUniformLocation(s_sobj[i].program, "u_TexDim");
415 set_projection_matrix(w, h);
417 return MEDIA_VISION_ERROR_NONE;
420 typedef struct _texparam {
430 unsigned int blendfunc[4];
431 float *user_texcoord;
434 static void draw_2d_texture_in(texparam_t *tparam)
436 int ttype = tparam->textype;
437 int texid = tparam->texid;
442 float rot = tparam->rot;
443 shader_obj_t *sobj = &s_sobj[ttype];
447 glBindBuffer(GL_ARRAY_BUFFER, 0);
448 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
450 glUseProgram(sobj->program);
451 glUniform1i(sobj->loc_tex, 0);
457 case 4: /* tex_yuyv */
458 glBindTexture(GL_TEXTURE_2D, texid);
459 uv = tparam->upsidedown ? tarray2 : tarray;
461 case 2: /* tex_extex */
462 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texid);
463 uv = tparam->upsidedown ? tarray : tarray2;
469 if (tparam->user_texcoord)
470 uv = tparam->user_texcoord;
472 if (sobj->loc_uv >= 0) {
473 glEnableVertexAttribArray(sobj->loc_uv);
474 glVertexAttribPointer(sobj->loc_uv, 2, GL_FLOAT, GL_FALSE, 0, uv);
479 if (tparam->blendfunc_en) {
480 glBlendFuncSeparate(tparam->blendfunc[0], tparam->blendfunc[1], tparam->blendfunc[2], tparam->blendfunc[3]);
482 glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
485 if (matrix_identity(matrix) != MEDIA_VISION_ERROR_NONE)
486 LOGE("Failed to call matrix_identity");
487 if (matrix_translate(matrix, x, y, 0.0f) != MEDIA_VISION_ERROR_NONE)
488 LOGE("Failed to call matrix_translate");
491 float px = tparam->px;
492 float py = tparam->py;
493 if (matrix_translate(matrix, px, py, 0.0f) != MEDIA_VISION_ERROR_NONE)
494 LOGE("Failed to call matrix_translate");
496 if (matrix_rotate(matrix, rot, 0.0f, 0.0f, 1.0f) != MEDIA_VISION_ERROR_NONE)
497 LOGE("Failed to call matrix_rotate");
498 if (matrix_translate(matrix, -px, -py, 0.0f) != MEDIA_VISION_ERROR_NONE)
499 LOGE("Failed to call matrix_translate");
501 if (matrix_scale(matrix, w, h, 1.0f) != MEDIA_VISION_ERROR_NONE)
502 LOGE("Failed to call matrix_scale");
503 if (matrix_mult(matrix, s_matprj, matrix) != MEDIA_VISION_ERROR_NONE)
504 LOGE("Failed to call matrix_mult");
506 glUniformMatrix4fv(s_loc_mtx[ttype], 1, GL_FALSE, matrix);
507 glUniform4fv(s_loc_color[ttype], 1, tparam->color);
509 if (s_loc_texdim[ttype] >= 0) {
511 texdim[0] = tparam->texw;
512 texdim[1] = tparam->texh;
513 glUniform2fv(s_loc_texdim[ttype], 1, texdim);
516 if (sobj->loc_vtx >= 0) {
517 glEnableVertexAttribArray(sobj->loc_vtx);
518 glVertexAttribPointer(sobj->loc_vtx, 2, GL_FLOAT, GL_FALSE, 0, varray);
521 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
526 int load_texture(mv_source_h source, int *lpTexID, int *lpWidth, int *lpHeight)
529 unsigned char *data_buffer = NULL;
530 unsigned int width, height;
531 unsigned int buffer_size = 0;
532 int err = mv_source_get_buffer(source, &data_buffer, &buffer_size);
533 if (MEDIA_VISION_ERROR_NONE != err) {
534 LOGE("ERROR: Errors were occurred during getting buffer from the "
540 err = mv_source_get_width(source, &width);
541 if (MEDIA_VISION_ERROR_NONE != err) {
542 LOGE("ERROR: Errors were occurred during getting width from the "
548 err = mv_source_get_height(source, &height);
549 if (MEDIA_VISION_ERROR_NONE != err) {
550 LOGE("ERROR: Errors were occurred during getting height from the "
555 texid = create_2d_texture(data_buffer, width, height);
564 return MEDIA_VISION_ERROR_NONE;
567 int draw_2d_texture(texture_2d_t *tex, int x, int y, int w, int h, int upsidedown)
569 texparam_t tparam = { 0 };
573 return MEDIA_VISION_ERROR_INTERNAL;
580 tparam.texid = tex->texid;
582 tparam.texw = tex->width;
583 tparam.texh = tex->height;
584 tparam.color[0] = 1.0f;
585 tparam.color[1] = 1.0f;
586 tparam.color[2] = 1.0f;
587 tparam.color[3] = 1.0f;
588 tparam.upsidedown = upsidedown;
590 if (tex->format == pixfmt_fourcc('Y', 'U', 'Y', 'V'))
593 draw_2d_texture_in(&tparam);
595 return MEDIA_VISION_ERROR_NONE;