LCOV - code coverage report
Current view: top level - compositor - visual_manager_3d_gl.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1017 1540 66.0 %
Date: 2021-04-29 23:48:07 Functions: 49 55 89.1 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2020
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / Scene Compositor sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include "visual_manager.h"
      27             : #include "texturing.h"
      28             : 
      29             : #ifndef GPAC_DISABLE_3D
      30             : 
      31             : #include <gpac/options.h>
      32             : #include <gpac/nodes_mpeg4.h>
      33             : #include "gl_inc.h"
      34             : 
      35             : #if (defined(WIN32) || defined(_WIN32_WCE)) && !defined(__GNUC__)
      36             : # if defined(GPAC_USE_TINYGL)
      37             : #  pragma comment(lib, "TinyGL")
      38             : 
      39             : # elif defined(GPAC_USE_GLES1X)
      40             : 
      41             : #  if 0
      42             : #   pragma message("Using OpenGL-ES Common Lite Profile")
      43             : #   pragma comment(lib, "libGLES_CL")
      44             : #       define GL_ES_CL_PROFILE
      45             : #  else
      46             : #   pragma message("Using OpenGL-ES Common Profile")
      47             : #   pragma comment(lib, "libGLES_CM")
      48             : #  endif
      49             : 
      50             : # elif defined(GPAC_USE_GLES2)
      51             : #  pragma comment(lib, "libGLESv2")
      52             : 
      53             : # else
      54             : #  pragma comment(lib, "opengl32")
      55             : # endif
      56             : 
      57             : #ifdef GPAC_HAS_GLU
      58             : #  pragma comment(lib, "glu32")
      59             : #endif
      60             : 
      61             : #endif
      62             : 
      63             : /*!! HORRIBLE HACK, but on my test devices, it seems that glClipPlanex is missing on the device but not in the SDK lib !!*/
      64             : #if defined(GL_MAX_CLIP_PLANES) && defined(__SYMBIAN32__)
      65             : #undef GL_MAX_CLIP_PLANES
      66             : #endif
      67             : 
      68             : #define CHECK_GL_EXT(name) ((strstr(ext, name) != NULL) ? 1 : 0)
      69             : 
      70             : 
      71         872 : void gf_sc_load_opengl_extensions(GF_Compositor *compositor, Bool has_gl_context)
      72             : {
      73             : #ifdef GPAC_USE_TINYGL
      74             :         /*let TGL handle texturing*/
      75             :         compositor->gl_caps.rect_texture = 1;
      76             :         compositor->gl_caps.npot_texture = 1;
      77             : #else
      78             :         const char *ext = NULL;
      79             : 
      80         872 :         if (has_gl_context)
      81         267 :                 ext = (const char *) glGetString(GL_EXTENSIONS);
      82             : 
      83         267 :         if (!ext) ext = gf_opts_get_key("core", "glext");
      84             :         /*store OGL extension to config for app usage*/
      85         267 :         else if (gf_opts_get_key("core", "glext")==NULL)
      86         128 :                 gf_opts_set_key("core", "glext", ext ? ext : "None");
      87             : 
      88         872 :         if (!ext) return;
      89             : 
      90         300 :         memset(&compositor->gl_caps, 0, sizeof(GLCaps));
      91             : 
      92         300 :         if (CHECK_GL_EXT("GL_ARB_multisample") || CHECK_GL_EXT("GLX_ARB_multisample") || CHECK_GL_EXT("WGL_ARB_multisample"))
      93         300 :                 compositor->gl_caps.multisample = 1;
      94         300 :         if (CHECK_GL_EXT("GL_ARB_texture_non_power_of_two"))
      95         300 :                 compositor->gl_caps.npot_texture = 1;
      96         300 :         if (CHECK_GL_EXT("GL_EXT_abgr"))
      97         300 :                 compositor->gl_caps.abgr_texture = 1;
      98         300 :         if (CHECK_GL_EXT("GL_EXT_bgra"))
      99         300 :                 compositor->gl_caps.bgra_texture = 1;
     100         300 :         if (CHECK_GL_EXT("GL_EXT_framebuffer_object") || CHECK_GL_EXT("GL_ARB_framebuffer_object"))
     101         300 :                 compositor->gl_caps.fbo = 1;
     102         300 :         if (CHECK_GL_EXT("GL_ARB_texture_non_power_of_two"))
     103         300 :                 compositor->gl_caps.npot = 1;
     104             : 
     105             : 
     106         300 :         if (CHECK_GL_EXT("GL_ARB_point_parameters")) {
     107         300 :                 compositor->gl_caps.point_sprite = 1;
     108         300 :                 if (CHECK_GL_EXT("GL_ARB_point_sprite") || CHECK_GL_EXT("GL_NV_point_sprite")) {
     109         300 :                         compositor->gl_caps.point_sprite = 2;
     110             :                 }
     111             :         }
     112             : 
     113             : #ifdef GPAC_USE_GLES2
     114             :         compositor->gl_caps.vbo = 1;
     115             : #else
     116         300 :         if (CHECK_GL_EXT("GL_ARB_vertex_buffer_object")) {
     117         300 :                 compositor->gl_caps.vbo = 1;
     118             :         }
     119             : #endif
     120             : 
     121             : 
     122             : #ifndef GPAC_USE_GLES1X
     123         300 :         if (CHECK_GL_EXT("GL_EXT_texture_rectangle") || CHECK_GL_EXT("GL_NV_texture_rectangle")) {
     124         300 :                 compositor->gl_caps.rect_texture = 1;
     125             :         }
     126             : #endif
     127             : 
     128         300 :         if (CHECK_GL_EXT("EXT_unpack_subimage") ) {
     129           0 :                 compositor->gl_caps.gles2_unpack = 1;
     130             :         }
     131             :         
     132         300 :         if (!has_gl_context) return;
     133             : 
     134             : 
     135             :         /*we have a GL context, init the rest (proc addresses & co)*/
     136         267 :         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &compositor->gl_caps.max_texture_size);
     137             : 
     138         267 :         if (CHECK_GL_EXT("GL_ARB_pixel_buffer_object")) {
     139         267 :                 compositor->gl_caps.pbo=1;
     140             :         }
     141             : 
     142             : #ifdef LOAD_GL_2_0
     143             :         if (glCreateProgram != NULL) {
     144             :                 compositor->gl_caps.has_shaders = 1;
     145             : 
     146             : #ifndef GPAC_CONFIG_ANDROID
     147             :                 if (glGetAttribLocation == NULL) {
     148             :                         compositor->shader_mode_disabled = GF_TRUE;
     149             :                 }
     150             : #endif
     151             : 
     152             :         } else {
     153             :                 GF_LOG(GF_LOG_WARNING, GF_LOG_COMPOSE, ("[Compositor] OpenGL shaders not supported\n"));
     154             :         }
     155             : #endif //LOAD_GL_2_0
     156             : 
     157             : #endif //GPAC_USE_TINYGL
     158             : 
     159             : #ifdef GPAC_USE_GLES2
     160             :         compositor->gl_caps.has_shaders = GF_TRUE;
     161             : #elif defined (GL_VERSION_2_0)
     162         267 :         compositor->gl_caps.has_shaders = GF_TRUE;
     163             : #endif
     164             :         if (!compositor->gl_caps.has_shaders) {
     165             : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
     166             :                 compositor->shader_mode_disabled = GF_TRUE;
     167             : #endif
     168             :                 if (compositor->visual->autostereo_type > GF_3D_STEREO_LAST_SINGLE_BUFFER) {
     169             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] OpenGL shaders not supported - disabling auto-stereo output\n"));
     170             :                         compositor->visual->nb_views=1;
     171             :                         compositor->visual->autostereo_type = GF_3D_STEREO_NONE;
     172             :                         compositor->visual->camlay = GF_3D_CAMERA_STRAIGHT;
     173             :                 }
     174             :         }
     175             : 
     176             : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
     177         267 :         if (!compositor->shader_mode_disabled && compositor->vertshader && compositor->fragshader) {
     178         265 :                 if (!gf_file_exists(compositor->vertshader)) {
     179           2 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] GLES Vertex shader %s not found, disabling shaders\n", compositor->vertshader));
     180           2 :                         compositor->shader_mode_disabled = GF_TRUE;
     181             :                 }
     182             : 
     183         265 :                 if (!gf_file_exists(compositor->fragshader)) {
     184           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] GLES Fragment shader %s not found, disabling shaders\n", compositor->fragshader));
     185           0 :                         compositor->shader_mode_disabled = GF_TRUE;
     186             :                 }
     187             :         }
     188             : #endif
     189             : }
     190             : 
     191             : 
     192             : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
     193             : 
     194             : #ifdef GPAC_USE_GLES2
     195             : #define GLES_VERSION_STRING "#version 100 \n"
     196             : #else
     197             : #define GLES_VERSION_STRING "#version 120 \n"
     198             : #endif
     199             : 
     200             : #define GLSL_PREFIX GLES_VERSION_STRING \
     201             :         "#ifdef GL_ES\n"\
     202             :         "#ifdef GL_FRAGMENT_PRECISION_HIGH\n"\
     203             :         "precision highp float;\n"\
     204             :         "#else\n"\
     205             :         "precision mediump float;\n"\
     206             :         "#endif\n" \
     207             :         "#endif\n"
     208             : 
     209             : static char *glsl_autostereo_vertex = GLSL_PREFIX "\
     210             :         attribute vec4 gfVertex;\
     211             :         attribute vec2 gfTextureCoordinates;\
     212             :         uniform mat4 gfProjectionMatrix;\
     213             :         varying vec2 TexCoord;\
     214             :         void main(void)\
     215             :         {\
     216             :                 TexCoord = gfTextureCoordinates;\
     217             :                 gl_Position = gfProjectionMatrix * gfVertex;\
     218             :         }";
     219             : 
     220             : static char *glsl_view_anaglyph = GLSL_PREFIX "\
     221             :         uniform sampler2D gfView1;\
     222             :         uniform sampler2D gfView2;\
     223             :         varying vec2 TexCoord;\
     224             :         void main(void)  \
     225             :         {\
     226             :                 vec4 col1 = texture2D(gfView1, TexCoord.st); \
     227             :                 vec4 col2 = texture2D(gfView2, TexCoord.st); \
     228             :                 gl_FragColor.r = col1.r;\
     229             :                 gl_FragColor.g = col2.g;\
     230             :                 gl_FragColor.b = col2.b;\
     231             :         }";
     232             : 
     233             : #ifdef GPAC_UNUSED_FUNC
     234             : static char *glsl_view_anaglyph_optimize = GLSL_PREFIX "\
     235             :         uniform sampler2D gfView1;\
     236             :         uniform sampler2D gfView2;\
     237             :         varying vec2 TexCoord;\
     238             :         void main(void)  \
     239             :         {\
     240             :                 vec4 col1 = texture2D(gfView1, TexCoord.st); \
     241             :                 vec4 col2 = texture2D(gfView2, TexCoord.st); \
     242             :                 gl_FragColor.r = 0.7*col1.g + 0.3*col1.b;\
     243             :                 gl_FragColor.r = pow(gl_FragColor.r, 1.5);\
     244             :                 gl_FragColor.g = col2.g;\
     245             :                 gl_FragColor.b = col2.b;\
     246             :         }";
     247             : #endif /*GPAC_UNUSED_FUNC*/
     248             : 
     249             : static char *glsl_view_columns = GLSL_PREFIX "\
     250             :         uniform sampler2D gfView1;\
     251             :         uniform sampler2D gfView2;\
     252             :         varying vec2 TexCoord;\
     253             :         void main(void)  \
     254             :         {\
     255             :                 if ( int( mod(gl_FragCoord.x, 2.0) ) == 0) \
     256             :                         gl_FragColor = texture2D(gfView1, TexCoord.st); \
     257             :                 else \
     258             :                         gl_FragColor = texture2D(gfView2, TexCoord.st); \
     259             :         }";
     260             : 
     261             : static char *glsl_view_rows = GLSL_PREFIX "\
     262             :         uniform sampler2D gfView1;\
     263             :         uniform sampler2D gfView2;\
     264             :         varying vec2 TexCoord;\
     265             :         void main(void)  \
     266             :         {\
     267             :                 if ( int( mod(gl_FragCoord.y, 2.0) ) == 0) \
     268             :                         gl_FragColor = texture2D(gfView1, TexCoord.st); \
     269             :                 else \
     270             :                         gl_FragColor = texture2D(gfView2, TexCoord.st); \
     271             :         }";
     272             : 
     273             : static char *glsl_view_5VSP19 = GLSL_PREFIX "\
     274             :         uniform sampler2D gfView1;\
     275             :         uniform sampler2D gfView2;\
     276             :         uniform sampler2D gfView3;\
     277             :         uniform sampler2D gfView4;\
     278             :         uniform sampler2D gfView5;\
     279             :         varying vec2 TexCoord;\
     280             :         \
     281             :         void getTextureSample(in int texID, out vec4 color) { \
     282             :           if (texID == 0 ) color = texture2D(gfView1, TexCoord.st); \
     283             :           else if (texID == 1 ) color = texture2D(gfView2, TexCoord.st); \
     284             :           else if (texID == 2 ) color = texture2D(gfView3, TexCoord.st); \
     285             :           else if (texID == 3 ) color = texture2D(gfView4, TexCoord.st); \
     286             :           else if (texID == 4 ) color = texture2D(gfView5, TexCoord.st); \
     287             :         } \
     288             :         \
     289             :         void main(void) {\
     290             :                 vec4 color;\
     291             :                 float pitch = 5.0 + 1.0  - mod(gl_FragCoord.y , 5.0);\
     292             :                 int col = int( mod(pitch + 3.0 * (gl_FragCoord.x), 5.0 ) );\
     293             :                 int Vr = int(col);\
     294             :                 int Vg = int(col) + 1;\
     295             :                 int Vb = int(col) + 2;\
     296             :                 if (Vg >= 5) Vg -= 5;\
     297             :                 if (Vb >= 5) Vb -= 5;\
     298             :                 getTextureSample(Vr, color); \
     299             :                 gl_FragColor.r = color.r;\
     300             :                 getTextureSample(Vg, color); \
     301             :                 gl_FragColor.g = color.g;\
     302             :                 getTextureSample(Vb, color); \
     303             :                 gl_FragColor.b = color.b;\
     304             :         }";
     305             : 
     306             : static char *glsl_view_8VAlio = GLSL_PREFIX "\
     307             :         uniform sampler2D gfView1; \
     308             :         uniform sampler2D gfView2; \
     309             :         uniform sampler2D gfView3; \
     310             :         uniform sampler2D gfView4; \
     311             :         uniform sampler2D gfView5; \
     312             :         uniform sampler2D gfView6; \
     313             :         uniform sampler2D gfView7; \
     314             :         uniform sampler2D gfView8; \
     315             :         varying vec2 TexCoord;\
     316             :          \
     317             :         void getTextureSample(in int texID, out vec4 color) { \
     318             :           if (texID == 0 ) color = texture2D(gfView1, TexCoord.st); \
     319             :           else if (texID == 1 ) color = texture2D(gfView2, TexCoord.st); \
     320             :           else if (texID == 2 ) color = texture2D(gfView3, TexCoord.st); \
     321             :           else if (texID == 3 ) color = texture2D(gfView4, TexCoord.st); \
     322             :           else if (texID == 4 ) color = texture2D(gfView5, TexCoord.st); \
     323             :           else if (texID == 5 ) color = texture2D(gfView6, TexCoord.st); \
     324             :           else if (texID == 6 ) color = texture2D(gfView7, TexCoord.st); \
     325             :           else if (texID == 7 ) color = texture2D(gfView8, TexCoord.st); \
     326             :         } \
     327             :          \
     328             :         void main() \
     329             :         { \
     330             :           int x = int(gl_FragCoord.x + 0.5); \
     331             :           int y = int(gl_FragCoord.y + 0.5); \
     332             :           int modulox = x/8; \
     333             :           int moduloy = y/8; \
     334             :           modulox = x - 8 * modulox; \
     335             :           moduloy = y - 8 * moduloy; \
     336             :            \
     337             :           int viewLine = 7 - moduloy; \
     338             :           int viewPix = viewLine + 3 * modulox; \
     339             :           int viewR = viewPix - 8*(viewPix/8); \
     340             :           int viewG = viewPix + 1 - 8*((viewPix +1)/8); \
     341             :           int viewB = viewPix + 2 - 8*((viewPix +2)/8); \
     342             :            \
     343             :           vec4 color; \
     344             :           getTextureSample(viewR, color); \
     345             :           gl_FragColor.r = color.r; \
     346             :           getTextureSample(viewG, color);  \
     347             :           gl_FragColor.g = color.g; \
     348             :           getTextureSample(viewB, color); \
     349             :           gl_FragColor.b = color.b; \
     350             :         }";
     351             : 
     352             : 
     353             : /**
     354             :  parses (glShaderSource) and compiles (glCompileShader) shader source
     355             : \return GF_TRUE if successful
     356             :  */
     357        1896 : Bool visual_3d_compile_shader(GF_SHADERID shader_id, const char *name, const char *source)
     358             : {
     359        1896 :         GLint blen = 0;
     360        1896 :         GLsizei slen = 0;
     361             :         s32 len;
     362        1896 :         GLint is_compiled=0;
     363        1896 :         if (!source || !shader_id) return 0;
     364        1896 :         len = (u32) strlen(source);
     365        1896 :         glShaderSource(shader_id, 1, &source, &len);
     366        1896 :         glCompileShader(shader_id);
     367             : 
     368        1896 :         glGetShaderiv(shader_id, GL_COMPILE_STATUS, &is_compiled);
     369        1896 :         if (is_compiled == GL_TRUE) return GF_TRUE;
     370           0 :         glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH , &blen);
     371           0 :         if (blen > 1) {
     372           0 :                 char* compiler_log = (char*) gf_malloc(blen);
     373             : #ifdef CONFIG_DARWIN_GL
     374             :                 glGetInfoLogARB((GLhandleARB) shader_id, blen, &slen, compiler_log);
     375             : #elif defined(GPAC_USE_GLES2)
     376             :                 glGetShaderInfoLog(shader_id, blen, &slen, compiler_log);
     377             : #else
     378           0 :                 glGetInfoLogARB(shader_id, blen, &slen, compiler_log);
     379             : #endif
     380           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[GLSL] Failed to compile %s shader: %s\n", name, compiler_log));
     381           0 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[GLSL] ***** faulty shader code ****\n%s\n**********************\n", source));
     382           0 :                 gf_free (compiler_log);
     383           0 :                 return 0;
     384             :         }
     385             :         return 1;
     386             : }
     387           0 : static GF_SHADERID visual_3d_shader_from_source_file(const char *src_path, u32 shader_type)
     388             : {
     389             :         GF_SHADERID shader = 0;
     390             :         u32 size;
     391             :         char *shader_src;
     392             : 
     393           0 :         GF_Err e = gf_file_load_data(src_path, (u8 **) &shader_src, &size);
     394           0 :         if (e) {
     395           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to open shader file %s: %s\n", src_path, gf_error_to_string(e) ));
     396             :         } else {
     397           0 :                 shader = glCreateShader(shader_type);
     398           0 :                 if (visual_3d_compile_shader(shader, (shader_type == GL_FRAGMENT_SHADER) ? "fragment" : "vertex", shader_src)==GF_FALSE) {
     399           0 :                         glDeleteShader(shader);
     400             :                         shader = 0;
     401             :                 }
     402           0 :                 gf_free(shader_src);
     403             :         }
     404           0 :         return shader;
     405             : }
     406             : 
     407             : #ifdef GPAC_CONFIG_IOS
     408             : #include <errno.h>
     409             : #include <sys/sysctl.h>
     410             : #endif
     411             : 
     412             : 
     413        1894 : static GF_SHADERID visual_3d_shader_with_flags(const char *src_path, u32 shader_type, u32 flags, u32 pixfmt) {
     414             : 
     415             :         GF_SHADERID shader = 0;
     416             :         char *defs, szKey[100];
     417             :         size_t str_size;
     418             : 
     419        1894 :         defs = (char *) gf_strdup(GLES_VERSION_STRING);
     420        1894 :         str_size = strlen(defs) + 1; //+1 for trailing \0
     421             : 
     422        1894 :         if (flags & GF_GL_HAS_LIGHT) {
     423             :                 sprintf(szKey, "#define GF_GL_HAS_LIGHT\n#define LIGHTS_MAX %d\n", GF_MAX_GL_LIGHTS);
     424         142 :                 str_size += strlen(szKey);
     425         142 :                 defs = (char *) gf_realloc(defs, sizeof(char)*str_size);
     426             :                 strcat(defs, szKey);
     427             :         }
     428             : 
     429        1894 :         if(flags & GF_GL_HAS_COLOR) {
     430          36 :                 str_size += strlen("#define GF_GL_HAS_COLOR \n");
     431          36 :                 defs = (char *) gf_realloc(defs, sizeof(char)*str_size);
     432             :                 strcat(defs,"#define GF_GL_HAS_COLOR \n");
     433             :         }
     434             : 
     435        1894 :         if(flags & GF_GL_HAS_TEXTURE) {
     436         256 :                 str_size += strlen("#define GF_GL_HAS_TEXTURE \n");
     437         256 :                 defs = (char *) gf_realloc(defs, sizeof(char)*str_size);
     438             :                 strcat(defs,"#define GF_GL_HAS_TEXTURE \n");
     439             :         }
     440             : 
     441        1894 :         if(flags & GF_GL_HAS_CLIP) {
     442             :                 /*clipping is always enabled*/
     443             :                 sprintf(szKey, "#define CLIPS_MAX %d\n#define GF_GL_HAS_CLIP\n", GF_MAX_GL_CLIPS);
     444           4 :                 str_size += strlen(szKey);
     445           4 :                 defs = (char *) gf_realloc(defs, sizeof(char)*str_size);
     446             :                 strcat(defs, szKey);
     447             :         }
     448             : 
     449        1894 :         if (shader_type==GL_FRAGMENT_SHADER) {
     450         947 :                 if(flags & GF_GL_IS_YUV) {
     451           0 :                         str_size += strlen("#define GF_GL_IS_YUV \n");
     452           0 :                         defs = (char *) gf_realloc(defs, sizeof(char)*str_size);
     453             :                         strcat(defs,"#define GF_GL_IS_YUV \n");
     454             :                 }
     455         947 :                 if(flags & GF_GL_IS_ExternalOES) {
     456           0 :                         str_size += strlen("#define GF_GL_IS_ExternalOES \n");
     457           0 :                         defs = (char *) gf_realloc(defs, sizeof(char)*str_size);
     458             :                         strcat(defs,"#define GF_GL_IS_ExternalOES \n");
     459             :                 }
     460             :         }
     461             : 
     462             :         char *shader_src;
     463             :         u32 size;
     464        1894 :         GF_Err e = gf_file_load_data(src_path ,(u8 **) &shader_src, &size);
     465             : 
     466        1894 :         if (e) {
     467           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to open shader file %s: %s\n", src_path, gf_error_to_string(e)));
     468             :         } else {
     469        1894 :                 char *final_src = NULL;
     470             : 
     471        1894 :                 gf_dynstrcat(&final_src, defs, NULL);
     472             : 
     473        1894 :                 if ((shader_type==GL_FRAGMENT_SHADER) && (flags & GF_GL_HAS_TEXTURE)) {
     474         128 :                         char *sep = strstr(shader_src, "void main(");
     475         128 :                         if (sep) sep[0] = 0;
     476         128 :                         gf_dynstrcat(&final_src, shader_src, NULL);
     477             : 
     478             :                         //add texture code
     479         128 :                         gf_gl_txw_insert_fragment_shader(pixfmt, "maintx", &final_src);
     480             : 
     481             :                         //append the rest
     482         128 :                         if (sep) {
     483         128 :                                 sep[0] = 'v';
     484         128 :                                 gf_dynstrcat(&final_src, sep, "\n");
     485             :                         }
     486             :                 } else {
     487        1766 :                         gf_dynstrcat(&final_src, shader_src, "\n");
     488             :                 }
     489        1894 :                 shader = glCreateShader(shader_type);
     490             : 
     491        1894 :                 if (visual_3d_compile_shader(shader, (shader_type == GL_FRAGMENT_SHADER) ? "fragment" : "vertex", final_src)==GF_FALSE) {
     492           0 :                         glDeleteShader(shader);
     493             :                         shader = 0;
     494             :                 }
     495             : 
     496        1894 :                 gf_free(shader_src);
     497        1894 :                 gf_free(final_src);
     498        1894 :                 gf_free(defs);
     499             :         }
     500        1894 :         return shader;
     501             : }
     502             : 
     503           1 : void visual_3d_init_stereo_shaders(GF_VisualManager *visual)
     504             : {
     505             :         GLint linked;
     506             :         Bool res;
     507           1 :         if (!visual->compositor->gl_caps.has_shaders) return;
     508             : 
     509           1 :         if (visual->autostereo_glsl_program) return;
     510             : 
     511           1 :         visual->autostereo_glsl_program = glCreateProgram();
     512             : 
     513             :         res = GF_TRUE;
     514           1 :         if (!visual->base_glsl_vertex) {
     515           1 :                 visual->base_glsl_vertex = glCreateShader(GL_VERTEX_SHADER);
     516           1 :                 res = visual_3d_compile_shader(visual->base_glsl_vertex, "vertex", glsl_autostereo_vertex);
     517             :         }
     518           1 :         if (res) {
     519           1 :                 switch (visual->autostereo_type) {
     520           0 :                 case GF_3D_STEREO_COLUMNS:
     521           0 :                         visual->autostereo_glsl_fragment = glCreateShader(GL_FRAGMENT_SHADER);
     522           0 :                         res = visual_3d_compile_shader(visual->autostereo_glsl_fragment, "fragment", glsl_view_columns);
     523           0 :                         break;
     524           0 :                 case GF_3D_STEREO_ROWS:
     525           0 :                         visual->autostereo_glsl_fragment = glCreateShader(GL_FRAGMENT_SHADER);
     526           0 :                         res = visual_3d_compile_shader(visual->autostereo_glsl_fragment, "fragment", glsl_view_rows);
     527           0 :                         break;
     528           0 :                 case GF_3D_STEREO_ANAGLYPH:
     529           0 :                         visual->autostereo_glsl_fragment = glCreateShader(GL_FRAGMENT_SHADER);
     530           0 :                         res = visual_3d_compile_shader(visual->autostereo_glsl_fragment, "fragment", glsl_view_anaglyph);
     531           0 :                         break;
     532           1 :                 case GF_3D_STEREO_5VSP19:
     533           1 :                         visual->autostereo_glsl_fragment = glCreateShader(GL_FRAGMENT_SHADER);
     534           1 :                         res = visual_3d_compile_shader(visual->autostereo_glsl_fragment, "fragment", glsl_view_5VSP19);
     535           1 :                         break;
     536           0 :                 case GF_3D_STEREO_8VALIO:
     537           0 :                         visual->autostereo_glsl_fragment = glCreateShader(GL_FRAGMENT_SHADER);
     538           0 :                         res = visual_3d_compile_shader(visual->autostereo_glsl_fragment, "fragment", glsl_view_8VAlio);
     539           0 :                         break;
     540             : 
     541           0 :                 case GF_3D_STEREO_CUSTOM:
     542           0 :                         visual->autostereo_glsl_fragment = visual_3d_shader_from_source_file(visual->compositor->mvshader, GL_FRAGMENT_SHADER);
     543           0 :                         if (visual->autostereo_glsl_fragment) res = GF_TRUE;
     544             :                         break;
     545             :                 }
     546             :         }
     547             : 
     548           1 :         if (res) {
     549           1 :                 glAttachShader(visual->autostereo_glsl_program, visual->base_glsl_vertex);
     550           1 :                 glAttachShader(visual->autostereo_glsl_program, visual->autostereo_glsl_fragment);
     551           1 :                 glLinkProgram(visual->autostereo_glsl_program);
     552             : 
     553           1 :                 glGetProgramiv(visual->autostereo_glsl_program, GL_LINK_STATUS, &linked);
     554           1 :                 if (!linked) {
     555             :                         int i32CharsWritten, i32InfoLogLength;
     556             :                         char pszInfoLog[2048];
     557           0 :                         glGetProgramiv(visual->autostereo_glsl_program, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
     558           0 :                         glGetProgramInfoLog(visual->autostereo_glsl_program, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
     559           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, (pszInfoLog));
     560             :                         res = GF_FALSE;
     561             :                 }
     562             :                 GL_CHECK_ERR()
     563             :         }
     564             : 
     565           1 :         if (!res) {
     566           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[V3D:GLSL] Autostereo vertex shader failed - disabling stereo support\n"));
     567           0 :                 visual->autostereo_type = 0;
     568           0 :                 visual->nb_views = 1;
     569             :         }
     570             : }
     571             : 
     572             : #define DEL_SHADER(_a) if (_a) { glDeleteShader(_a); _a = 0; }
     573             : #define DEL_PROGRAM(_a) if (_a) { glDeleteProgram(_a); _a = 0; }
     574             : 
     575             : 
     576             : 
     577             : #if 0
     578             : static GLint gf_glGetUniformLocation(GF_SHADERID glsl_program, const char *uniform_name)
     579             : {
     580             :         GLint loc = glGetUniformLocation(glsl_program, uniform_name);
     581             :         if (loc<0) {
     582             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[V3D:GLSL] Cannot find uniform \"%s\" in GLSL program\n", uniform_name));
     583             :         }
     584             :         return loc;
     585             : }
     586             : #endif
     587             : 
     588             : 
     589             : #if 0
     590             : static GLint gf_glGetAttribLocation(GF_SHADERID glsl_program, const char *attrib_name)
     591             : {
     592             :         GLint loc = glGetAttribLocation(glsl_program, attrib_name);
     593             :         if (loc<0) {
     594             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[V3D:GLSL] Cannot find attrib \"%s\" in GLSL program\n", attrib_name));
     595             :         }
     596             :         return loc;
     597             : }
     598             : #endif
     599             : 
     600             : //The following functions were used for shader testing [in ES2.0]
     601             : #if 0
     602             : static void gf_glQueryProgram(GF_SHADERID progObj)
     603             : {
     604             :         GLint err_log = -10;
     605             :         GL_CHECK_ERR()
     606             :         glValidateProgram(progObj);
     607             :         GL_CHECK_ERR()
     608             :         glGetProgramiv(progObj, GL_VALIDATE_STATUS, &err_log);
     609             :         printf("GL_VALIDATE_STATUS: %d \n ",err_log);
     610             :         glGetProgramiv(progObj, GL_LINK_STATUS, &err_log);
     611             :         printf("GL_LINK_STATUS: %d \n ",err_log);
     612             :         glGetProgramiv(progObj, GL_ATTACHED_SHADERS, &err_log);
     613             :         printf("GL_ATTACHED_SHADERS: %d \n ",err_log);
     614             :         glGetProgramiv(progObj, GL_ACTIVE_UNIFORMS, &err_log);
     615             :         printf("GL_ACTIVE_UNIFORMS: %d \n ",err_log);
     616             : }
     617             : 
     618             : static void gf_glQueryUniform(GF_SHADERID progObj, const char *name, int index)
     619             : {
     620             :         GLint loc, i;
     621             :         GLfloat res[16];
     622             : 
     623             :         loc = glGetUniformLocation(progObj, name);
     624             :         if(loc<0) {
     625             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("failed to locate uniform. exiting\n"));
     626             :                 return;
     627             :         }
     628             :         glGetUniformfv(progObj, loc, (GLfloat *) res);
     629             :         GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("uniform %s has value of: ", name));
     630             :         for (i =0; i<index; i++)
     631             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("%f ", res[i]));
     632             : }
     633             : 
     634             : //same here
     635             : static void gf_glQueryAttrib(GF_SHADERID progObj, const char *name, int index, GLenum param)
     636             : {
     637             :         GLint loc, i;
     638             :         GLfloat res[16];
     639             : 
     640             :         loc = glGetAttribLocation(progObj, name);
     641             :         if (loc<0) {
     642             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("failed to locate attribute. exiting\n"));
     643             :                 return;
     644             :         }
     645             :         glGetVertexAttribfv(loc, param, (GLfloat *) res);
     646             :         GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("attribute %s has value of: ", name));
     647             :         for( i =0; i<index; i++)
     648             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("%f ", res[i]));
     649             : }
     650             : 
     651             : static void gf_glQueryUniforms(GF_SHADERID progObj)
     652             : {
     653             :         GLint maxUniformLen;
     654             :         GLint numUniforms;
     655             :         char *uniformName;
     656             :         GLint index;
     657             : 
     658             :         glGetProgramiv(progObj, GL_ACTIVE_UNIFORMS, &numUniforms);
     659             :         glGetProgramiv(progObj, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);
     660             :         uniformName = gf_malloc(sizeof(char) * maxUniformLen);
     661             :         for(index = 0; index < numUniforms; index++) {
     662             :                 GLint size;
     663             :                 GLenum type;
     664             :                 GLint location;
     665             :                 // Get the Uniform Info
     666             :                 glGetActiveUniform(progObj, index, maxUniformLen, NULL, &size, &type, uniformName);
     667             :                 // Get the uniform location
     668             :                 location = glGetUniformLocation(progObj, uniformName);
     669             :                 if(location) printf("uniform %s is: ",uniformName);
     670             :                 switch(type) {
     671             :                 case GL_FLOAT:
     672             :                         printf("float \n");
     673             :                         break;
     674             :                 case GL_FLOAT_VEC2:
     675             :                         printf("floatvec2 \n");
     676             :                         break;
     677             :                 case GL_FLOAT_VEC3:
     678             :                         printf("floatvec3 \n");
     679             :                         break;
     680             :                 case GL_FLOAT_VEC4:
     681             :                         printf("floatvec4 \n");
     682             :                         break;
     683             :                 case GL_INT:
     684             :                         printf("int \n");
     685             :                         break;
     686             :                 case GL_INT_VEC2:
     687             :                 case GL_INT_VEC3:
     688             :                 case GL_INT_VEC4:
     689             :                         printf("intVec \n");
     690             :                         break;
     691             :                 case GL_FLOAT_MAT2:
     692             :                 case GL_FLOAT_MAT3:
     693             :                 case GL_FLOAT_MAT4:
     694             :                         printf("fmat \n");
     695             :                         break;
     696             :                 case GL_SAMPLER_2D:
     697             :                         printf("samp2D \n");
     698             :                         break;
     699             :                 case GL_SAMPLER_CUBE:
     700             :                         printf("sampCube \n");
     701             :                         break;
     702             :                 default:
     703             :                         printf("other \n");
     704             :                         break;
     705             :                 }
     706             :         }
     707             :         gf_free(uniformName);
     708             : }
     709             : 
     710             : static void gf_glQueryAttributes(GF_SHADERID progObj)
     711             : {
     712             :         GLint maxAttributeLen;
     713             :         GLint numAttributes;
     714             :         char *attributeName;
     715             :         GLint index;
     716             : 
     717             :         printf("Listing Attribs... \n");
     718             :         glGetProgramiv(progObj, GL_ACTIVE_ATTRIBUTES, &numAttributes);
     719             :         glGetProgramiv(progObj, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeLen);
     720             :         attributeName = gf_malloc(sizeof(char) * maxAttributeLen);
     721             :         for(index = 0; index < numAttributes; index++) {
     722             :                 GLint size;
     723             :                 GLenum type;
     724             :                 GLint location;
     725             :                 // Get the Attribute Info
     726             :                 glGetActiveAttrib(progObj, index, maxAttributeLen, NULL, &size, &type, attributeName);
     727             :                 // Get the attribute location
     728             :                 location = glGetAttribLocation(progObj, attributeName);
     729             :                 if(location) printf("attrib %s is: ",attributeName);
     730             :                 switch(type) {
     731             :                 case GL_FLOAT:
     732             :                         printf("float \n");
     733             :                         break;
     734             :                 case GL_FLOAT_VEC2:
     735             :                         printf("floatvec2 \n");
     736             :                         break;
     737             :                 case GL_FLOAT_VEC3:
     738             :                         printf("floatvec3 \n");
     739             :                         break;
     740             :                 case GL_FLOAT_VEC4:
     741             :                         printf("floatvec4 \n");
     742             :                         break;
     743             :                 case GL_INT:
     744             :                         printf("int \n");
     745             :                         break;
     746             :                 case GL_INT_VEC2:
     747             :                 case GL_INT_VEC3:
     748             :                 case GL_INT_VEC4:
     749             :                         printf("intVec \n");
     750             :                         break;
     751             :                 case GL_FLOAT_MAT2:
     752             :                 case GL_FLOAT_MAT3:
     753             :                 case GL_FLOAT_MAT4:
     754             :                         printf("fmat \n");
     755             :                         break;
     756             :                 case GL_SAMPLER_2D:
     757             :                         printf("samp2D \n");
     758             :                         break;
     759             :                 case GL_SAMPLER_CUBE:
     760             :                         printf("sampCube \n");
     761             :                         break;
     762             :                 default:
     763             :                         printf("other \n");
     764             :                         break;
     765             :                 }
     766             :         }
     767             :         gf_free(attributeName);
     768             : }
     769             : #endif
     770             : 
     771         947 : static GF_GLProgInstance *visual_3d_build_program(GF_VisualManager *visual, u32 flags, u32 pix_fmt)
     772             : {
     773             :         s32 linked;
     774             :         GF_GLProgInstance *pi;
     775             : 
     776         947 :         GF_SAFEALLOC(pi, GF_GLProgInstance);
     777         947 :         if (!pi) return NULL;
     778         947 :         pi->flags = flags;
     779         947 :         pi->pix_fmt = pix_fmt;
     780             : 
     781         947 :         glGetError();
     782         947 :         pi->prog = glCreateProgram();
     783         947 :         if (!pi->prog) {
     784           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to create program\n"));
     785           0 :                 gf_free(pi);
     786             :                 return NULL;
     787             :         }
     788         947 :         pi->vertex = visual_3d_shader_with_flags(visual->compositor->vertshader , GL_VERTEX_SHADER, flags, 0);
     789         947 :         if (!pi->vertex) {
     790           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to compile vertex shader\n"));
     791           0 :                 DEL_PROGRAM(pi->prog)
     792           0 :                 gf_free(pi);
     793             :                 return NULL;
     794             :         }
     795         947 :         if (pix_fmt == GF_PIXEL_GL_EXTERNAL) {
     796           0 :                 flags |= GF_GL_IS_ExternalOES;
     797             :         }
     798         947 :         pi->fragment = visual_3d_shader_with_flags(visual->compositor->fragshader , GL_FRAGMENT_SHADER, flags, pix_fmt);
     799         947 :         if (!pi->fragment) {
     800           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to compile fragment shader\n"));
     801           0 :                 DEL_PROGRAM(pi->prog)
     802           0 :                 DEL_SHADER(pi->vertex);
     803           0 :                 gf_free(pi);
     804             :                 return NULL;
     805             :         }
     806         947 :         glAttachShader(pi->prog, pi->vertex);
     807             :         GL_CHECK_ERR();
     808         947 :         glAttachShader(pi->prog, pi->fragment);
     809             :         GL_CHECK_ERR();
     810             : 
     811         947 :         glLinkProgram(pi->prog);
     812             :         GL_CHECK_ERR();
     813             : 
     814         947 :         glGetProgramiv(pi->prog, GL_LINK_STATUS, &linked);
     815         947 :         if (!linked) {
     816             :                 int i32CharsWritten, i32InfoLogLength;
     817             :                 char pszInfoLog[2048];
     818           0 :                 glGetProgramiv(pi->prog, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
     819           0 :                 glGetProgramInfoLog(pi->prog, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
     820           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, (pszInfoLog));
     821           0 :                 DEL_PROGRAM(pi->prog)
     822           0 :                 DEL_SHADER(pi->vertex);
     823           0 :                 DEL_SHADER(pi->fragment);
     824           0 :                 gf_free(pi);
     825             :                 return NULL;
     826             :         }
     827         947 :         GF_LOG(GF_LOG_INFO, GF_LOG_COMPOSE, ("[Compositor] fragment shader compiled fine\n"));
     828             :         return pi;
     829             : }
     830             : 
     831        6627 : static Bool visual_3d_init_generic_shaders(GF_VisualManager *visual)
     832             : {
     833             :         GF_GLProgInstance *pi;
     834        6627 :         if (gf_list_count(visual->compiled_programs))
     835             :                 return GF_TRUE;
     836         708 :         if (!gf_file_exists(visual->compositor->vertshader))
     837             :                 return GF_FALSE;
     838         708 :         if (!gf_file_exists(visual->compositor->fragshader))
     839             :                 return GF_FALSE;
     840             : 
     841             : 
     842         708 :         pi = visual_3d_build_program(visual, 0, 0);
     843         708 :         if (!pi) return GF_FALSE;
     844             : 
     845         708 :         glDeleteShader(pi->vertex);
     846         708 :         glDeleteShader(pi->fragment);
     847         708 :         glDeleteProgram(pi->prog);
     848         708 :         gf_free(pi);
     849         708 :         return GF_TRUE;
     850             : }
     851             : 
     852        6806 : void visual_3d_init_shaders(GF_VisualManager *visual)
     853             : {
     854        6806 :         if (visual->compositor->visual != visual)
     855             :                 return;
     856             : 
     857        6806 :         if (!visual->compositor->gl_caps.has_shaders)
     858             :                 return;
     859             : 
     860        6806 :         if (!visual->compositor->shader_mode_disabled) {
     861             :                 //If we fail to configure shaders, force 2D mode
     862        6627 :                 if (! visual_3d_init_generic_shaders(visual)) {
     863           0 :                         visual->compositor->hybrid_opengl = GF_FALSE;
     864           0 :                         visual->compositor->force_opengl_2d = GF_FALSE;
     865             :                         /*force resetup*/
     866           0 :                         visual->compositor->root_visual_setup = 0;
     867             :                         /*force texture setup when switching to OpenGL*/
     868           0 :                         gf_sc_reset_graphics(visual->compositor);
     869             :                         /*force redraw*/
     870           0 :                         gf_sc_next_frame_state(visual->compositor, GF_SC_DRAW_FRAME);
     871             :                 }
     872             :         }
     873             : }
     874             : 
     875             : #endif // !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
     876             : 
     877             : 
     878         651 : void visual_3d_reset_graphics(GF_VisualManager *visual)
     879             : {
     880             : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
     881         651 :         if (visual->compositor->visual != visual)
     882             :                 return;
     883             : 
     884         604 :         DEL_SHADER(visual->base_glsl_vertex);
     885         604 :         DEL_SHADER(visual->autostereo_glsl_fragment);
     886         604 :         DEL_PROGRAM(visual->autostereo_glsl_program );
     887             : 
     888         604 :         if (visual->gl_textures) {
     889           1 :                 glDeleteTextures(visual->nb_views, visual->gl_textures);
     890           1 :                 gf_free(visual->gl_textures);
     891           1 :                 visual->gl_textures = NULL;
     892             :         }
     893         604 :         if (visual->autostereo_mesh) {
     894           1 :                 mesh_free(visual->autostereo_mesh);
     895           1 :                 visual->autostereo_mesh = NULL;
     896             :         }
     897             : 
     898         841 :         while (gf_list_count(visual->compiled_programs)) {
     899         237 :                 GF_GLProgInstance *gi = gf_list_pop_back(visual->compiled_programs);
     900         237 :                 DEL_SHADER(gi->vertex);
     901         237 :                 DEL_SHADER(gi->fragment);
     902         237 :                 DEL_PROGRAM(gi->prog);
     903         237 :                 gf_free(gi);
     904             :         }
     905             : #endif
     906             : }
     907             : 
     908       63607 : void visual_3d_set_clipper_scissor(GF_VisualManager *visual, GF_TraverseState *tr_state)
     909             : {
     910             : #ifndef GPAC_USE_TINYGL
     911       63607 :         if (visual->has_clipper_2d) {
     912             :                 u32 x, y;
     913             :                 u32 dw, dh;
     914        3179 :                 glEnable(GL_SCISSOR_TEST);
     915             : 
     916        3179 :                 if (visual->offscreen) {
     917           0 :                         dw = visual->width;
     918           0 :                         dh = visual->height;
     919             :                 } else {
     920        3179 :                         dw = visual->compositor->display_width;
     921        3179 :                         dh = visual->compositor->display_height;
     922             :                 }
     923             : 
     924        3179 :                 if (visual->center_coords) {
     925        3173 :                         x = visual->clipper_2d.x + dw / 2;
     926        3173 :                         y = dh / 2 + visual->clipper_2d.y - visual->clipper_2d.height;
     927             :                 } else {
     928           6 :                         x = visual->clipper_2d.x;
     929           6 :                         y = dh - visual->clipper_2d.y;
     930             :                 }
     931        3179 :                 glScissor(x, y, visual->clipper_2d.width, visual->clipper_2d.height);
     932             :         } else {
     933       60428 :                 glDisable(GL_SCISSOR_TEST);
     934             :         }
     935             : #endif
     936       63607 : }
     937             : 
     938             : 
     939             : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
     940             : 
     941       94940 : static void visual_3d_load_matrix_shaders(GF_SHADERID program, Fixed *mat, const char *name)
     942             : {
     943             :         GLint loc;
     944             : #ifdef GPAC_FIXED_POINT
     945             :         Float _mat[16];
     946             :         u32 i;
     947             : #endif
     948             : 
     949       94940 :         loc = glGetUniformLocation(program, name);
     950       94940 :         if(loc<0) {
     951           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("GL Error (file %s line %d): Invalid matrix name", __FILE__, __LINE__));
     952             :                 return;
     953             :         }
     954             :         GL_CHECK_ERR()
     955             : 
     956             : #ifdef GPAC_FIXED_POINT
     957             :         for (i=0; i<16; i++) _mat[i] = FIX2FLT(mat[i]);
     958             :         glUniformMatrix4fv(loc, 1, GL_FALSE, (GLfloat *) _mat);
     959             : #else
     960       94940 :         glUniformMatrix4fv(loc, 1, GL_FALSE, mat);
     961             : #endif
     962             :         GL_CHECK_ERR()
     963             : }
     964             : 
     965             : #endif
     966             : 
     967         166 : GF_Err visual_3d_init_autostereo(GF_VisualManager *visual)
     968             : {
     969             : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
     970             :         u32 bw, bh;
     971             :         SFVec2f s;
     972         166 :         Bool use_npot = visual->compositor->gl_caps.npot_texture;
     973         166 :         if (visual->gl_textures) return GF_OK;
     974             : 
     975           1 :         visual->gl_textures = gf_malloc(sizeof(GLuint) * visual->nb_views);
     976           1 :         glGenTextures(visual->nb_views, visual->gl_textures);
     977             : 
     978           1 :         bw = visual->width;
     979           1 :         bh = visual->height;
     980             :         /*main (not offscreen) visual*/
     981           1 :         if (visual->compositor->visual==visual) {
     982           1 :                 bw = visual->compositor->output_width;
     983           1 :                 bh = visual->compositor->output_height;
     984             :         }
     985             : 
     986             : #ifdef GPAC_USE_GLES2
     987             :         use_npot = GF_TRUE;
     988             : #endif
     989             : 
     990           1 :         if (use_npot) {
     991           1 :                 visual->auto_stereo_width = bw;
     992           1 :                 visual->auto_stereo_height = bh;
     993             :         } else {
     994           0 :                 visual->auto_stereo_width = 2;
     995           0 :                 while (visual->auto_stereo_width < bw) visual->auto_stereo_width *= 2;
     996           0 :                 visual->auto_stereo_height = 2;
     997           0 :                 while (visual->auto_stereo_height < bh) visual->auto_stereo_height *= 2;
     998             :         }
     999             : 
    1000           1 :         visual->autostereo_mesh = new_mesh();
    1001           1 :         s.x = INT2FIX(bw);
    1002           1 :         s.y = INT2FIX(bh);
    1003           1 :         mesh_new_rectangle(visual->autostereo_mesh, s, NULL, 0);
    1004             : 
    1005           1 :         if (! use_npot) {
    1006             :                 u32 i;
    1007           0 :                 Fixed max_u = INT2FIX(bw) / visual->auto_stereo_width;
    1008           0 :                 Fixed max_v = INT2FIX(bh) / visual->auto_stereo_height;
    1009           0 :                 for (i=0; i<visual->autostereo_mesh->v_count; i++) {
    1010           0 :                         if (visual->autostereo_mesh->vertices[i].texcoords.x == FIX_ONE) {
    1011           0 :                                 visual->autostereo_mesh->vertices[i].texcoords.x = max_u;
    1012             :                         }
    1013           0 :                         if (visual->autostereo_mesh->vertices[i].texcoords.y == FIX_ONE) {
    1014           0 :                                 visual->autostereo_mesh->vertices[i].texcoords.y = max_v;
    1015             :                         }
    1016             :                 }
    1017             :         }
    1018             : 
    1019           1 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual3D] AutoStereo initialized - width %d height %d\n", visual->auto_stereo_width, visual->auto_stereo_height) );
    1020             : 
    1021           1 :         visual_3d_init_stereo_shaders(visual);
    1022             : #endif // !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
    1023             : 
    1024           1 :         return GF_OK;
    1025             : }
    1026             : 
    1027         830 : void visual_3d_end_auto_stereo_pass(GF_VisualManager *visual)
    1028             : {
    1029             : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
    1030             :         u32 i;
    1031             :         GLint loc, loc_vertex_attrib, loc_texcoord_attrib;
    1032             :         Fixed hw, hh;
    1033             :         GF_Matrix mx;
    1034             : 
    1035             : 
    1036         830 :         glFlush();
    1037             : 
    1038             :         GL_CHECK_ERR()
    1039             : 
    1040             : #ifndef GPAC_USE_GLES2
    1041         830 :         glEnable(GL_TEXTURE_2D);
    1042             : #endif
    1043             : 
    1044         830 :         glBindTexture(GL_TEXTURE_2D, visual->gl_textures[visual->current_view]);
    1045             : 
    1046             : #ifndef GPAC_USE_GLES2
    1047         830 :         glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
    1048         830 :         glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
    1049         830 :         glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    1050         830 :         glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    1051         830 :         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    1052         830 :         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    1053             : #else
    1054             :         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    1055             :         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    1056             :         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    1057             :         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    1058             :         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    1059             : #endif
    1060             : 
    1061         830 :         glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, visual->auto_stereo_width, visual->auto_stereo_height, 0);
    1062             :         GL_CHECK_ERR()
    1063             : 
    1064             : #ifndef GPAC_USE_GLES2
    1065         830 :         glDisable(GL_TEXTURE_2D);
    1066             : #endif
    1067             : 
    1068         830 :         glClear(GL_DEPTH_BUFFER_BIT);
    1069             :         GL_CHECK_ERR()
    1070             : 
    1071        1494 :         if (visual->current_view+1<visual->nb_views) return;
    1072         166 :         hw = INT2FIX(visual->width);
    1073         166 :         hh = INT2FIX(visual->height);
    1074             :         /*main (not offscreen) visual*/
    1075         166 :         if (visual->compositor->visual==visual) {
    1076         166 :                 hw = INT2FIX(visual->compositor->output_width);
    1077         166 :                 hh = INT2FIX(visual->compositor->output_height);
    1078             :         }
    1079             : 
    1080         166 :         glViewport(0, 0, (GLsizei) hw, (GLsizei) hh );
    1081             : 
    1082         166 :         hw /= 2;
    1083         166 :         hh /= 2;
    1084             : 
    1085             :         /*use our program*/
    1086         166 :         glUseProgram(visual->autostereo_glsl_program);
    1087             : 
    1088             :         //load projection
    1089         166 :         gf_mx_ortho(&mx, -hw, hw, -hh, hh, -10, 100);
    1090         166 :         visual_3d_load_matrix_shaders(visual->autostereo_glsl_program, mx.m, "gfProjectionMatrix");
    1091             : 
    1092             :         //no need for modelview (identifty)
    1093             : 
    1094             :         /*push number of views if shader uses it*/
    1095         166 :         loc = glGetUniformLocation(visual->autostereo_glsl_program, "gfViewCount");
    1096         166 :         if (loc != -1) glUniform1i(loc, visual->nb_views);
    1097             : 
    1098             :         loc_texcoord_attrib = -1;
    1099             :         //setup vertex attrib
    1100         166 :         loc_vertex_attrib = glGetAttribLocation(visual->autostereo_glsl_program, "gfVertex");
    1101         166 :         if (loc_vertex_attrib>=0) {
    1102         166 :                 glVertexAttribPointer(loc_vertex_attrib, 3, GL_FLOAT, GL_FALSE, sizeof(GF_Vertex), &visual->autostereo_mesh->vertices[0].pos);
    1103         166 :                 glEnableVertexAttribArray(loc_vertex_attrib);
    1104             : 
    1105             :                 GL_CHECK_ERR()
    1106             : 
    1107             :                 //setup texcoord location
    1108         166 :                 loc_texcoord_attrib = glGetAttribLocation(visual->autostereo_glsl_program, "gfTextureCoordinates");
    1109         166 :                 if (loc_texcoord_attrib>=0) {
    1110             :                         char szTex[100];
    1111         166 :                         glVertexAttribPointer(loc_texcoord_attrib, 2, GL_FLOAT, GL_FALSE, sizeof(GF_Vertex), &visual->autostereo_mesh->vertices[0].texcoords);
    1112         166 :                         glEnableVertexAttribArray(loc_texcoord_attrib);
    1113             : 
    1114             :                         GL_CHECK_ERR()
    1115             : 
    1116             :                         /*bind all our textures*/
    1117        1162 :                         for (i=0; i<visual->nb_views; i++) {
    1118         830 :                                 sprintf(szTex, "gfView%d", i+1);
    1119         830 :                                 loc = glGetUniformLocation(visual->autostereo_glsl_program, szTex);
    1120         830 :                                 if (loc == -1) continue;
    1121             : 
    1122         830 :                                 glActiveTexture(GL_TEXTURE0 + i);
    1123             : 
    1124             : #ifndef GPAC_USE_GLES2
    1125         830 :                                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    1126         830 :                                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    1127         830 :                                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    1128         830 :                                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    1129         830 :                                 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
    1130             : #endif
    1131             : 
    1132             :                                 GL_CHECK_ERR()
    1133             : 
    1134         830 :                                 glBindTexture(GL_TEXTURE_2D, visual->gl_textures[i]);
    1135             : 
    1136             :                                 GL_CHECK_ERR()
    1137             : 
    1138         830 :                                 glUniform1i(loc, i);
    1139             : 
    1140             :                                 GL_CHECK_ERR()
    1141             :                         }
    1142             : 
    1143             :                         //draw
    1144             : #if defined(GPAC_USE_GLES2)
    1145             :                         glDrawElements(GL_TRIANGLES, visual->autostereo_mesh->i_count, GL_UNSIGNED_SHORT, visual->autostereo_mesh->indices);
    1146             : #else
    1147         166 :                         glDrawElements(GL_TRIANGLES, visual->autostereo_mesh->i_count, GL_UNSIGNED_INT, visual->autostereo_mesh->indices);
    1148             : #endif
    1149             : 
    1150             :                         GL_CHECK_ERR()
    1151             :                 }
    1152             :         }
    1153             : 
    1154             : 
    1155         166 :         if (loc_vertex_attrib>=0) glDisableVertexAttribArray(loc_vertex_attrib);
    1156         166 :         if (loc_texcoord_attrib>=0) glDisableVertexAttribArray(loc_texcoord_attrib);
    1157             :         GL_CHECK_ERR()
    1158             : 
    1159         166 :         glUseProgram(0);
    1160             : 
    1161             : #ifndef GPAC_USE_GLES2
    1162             :         /*not sure why this is needed but it prevents a texturing bug on XP on parallels*/
    1163         166 :         glActiveTexture(GL_TEXTURE0);
    1164             :         GL_CHECK_ERR()
    1165             : 
    1166         166 :         glBindTexture(GL_TEXTURE_2D, 0);
    1167         166 :         glDisable(GL_TEXTURE_2D);
    1168             : #endif
    1169             : 
    1170             :         GL_CHECK_ERR()
    1171             : #endif // !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
    1172             : 
    1173             : }
    1174             : 
    1175             : 
    1176       12541 : static void visual_3d_setup_quality(GF_VisualManager *visual)
    1177             : {
    1178             : #ifndef GPAC_USE_GLES2
    1179             : 
    1180       12541 :         if (visual->compositor->fast) {
    1181           0 :                 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
    1182           0 :                 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
    1183           0 :                 glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
    1184             : #ifdef GL_POLYGON_SMOOTH_HINT
    1185           0 :                 glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
    1186             : #endif
    1187             :         } else {
    1188       12541 :                 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    1189       12541 :                 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    1190       12541 :                 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
    1191             : #ifdef GL_POLYGON_SMOOTH_HINT
    1192       12541 :                 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
    1193             : #endif
    1194             :         }
    1195             : 
    1196       12541 :         if (visual->compositor->aa == GF_ANTIALIAS_FULL) {
    1197       12541 :                 glEnable(GL_LINE_SMOOTH);
    1198             : #ifndef GPAC_USE_GLES1X
    1199       12541 :                 if (visual->compositor->paa)
    1200           0 :                         glEnable(GL_POLYGON_SMOOTH);
    1201             :                 else
    1202       12541 :                         glDisable(GL_POLYGON_SMOOTH);
    1203             : #endif
    1204             :         } else {
    1205           0 :                 glDisable(GL_LINE_SMOOTH);
    1206             : #ifndef GPAC_USE_GLES1X
    1207           0 :                 glDisable(GL_POLYGON_SMOOTH);
    1208             : #endif
    1209             :         }
    1210             : 
    1211             : #endif
    1212             : 
    1213       12541 : }
    1214             : 
    1215        8025 : void visual_3d_setup(GF_VisualManager *visual)
    1216             : {
    1217             :         //in non-player mode, we might not be the only ones using the gl context !!
    1218        8025 :         if (visual->compositor->player && visual->gl_setup) {
    1219         237 :                 visual->has_fog = GF_FALSE;
    1220         237 :                 glClear(GL_DEPTH_BUFFER_BIT);
    1221         237 :                 return;
    1222             :         }
    1223             : 
    1224             : #ifndef GPAC_USE_TINYGL
    1225        7788 :         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    1226        7788 :         glDepthFunc(GL_LEQUAL);
    1227             : #endif
    1228        7788 :         glEnable(GL_DEPTH_TEST);
    1229        7788 :         glFrontFace(GL_CCW);
    1230        7788 :         glCullFace(GL_BACK);
    1231             : 
    1232             : #ifdef GPAC_USE_GLES1X
    1233             :         glClearDepthx(FIX_ONE);
    1234             :         glLightModelx(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
    1235             :         glMaterialx(GL_FRONT_AND_BACK, GL_SHININESS, FLT2FIX(0.2f * 128) );
    1236             :         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    1237             : #elif defined(GPAC_USE_GLES2)
    1238             :         glClearDepthf(1.0f);
    1239             : #else
    1240        7788 :         glClearDepth(1.0f);
    1241        7788 :         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
    1242        7788 :         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
    1243        7788 :         glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, (float) (0.2 * 128));
    1244             : #endif
    1245             : 
    1246             : 
    1247             : #ifndef GPAC_USE_GLES2
    1248        7788 :         glDisable(GL_TEXTURE_2D);
    1249        7788 :         glShadeModel(GL_SMOOTH);
    1250        7788 :         glGetIntegerv(GL_MAX_LIGHTS, (GLint*)&visual->max_lights);
    1251        7788 :         if (visual->max_lights>GF_MAX_GL_LIGHTS)
    1252        7788 :                 visual->max_lights=GF_MAX_GL_LIGHTS;
    1253             : 
    1254             : #ifdef GL_MAX_CLIP_PLANES
    1255        7788 :         glGetIntegerv(GL_MAX_CLIP_PLANES, (GLint*)&visual->max_clips);
    1256        7788 :         if (visual->max_clips>GF_MAX_GL_CLIPS)
    1257        7788 :                 visual->max_clips=GF_MAX_GL_CLIPS;
    1258             : #endif
    1259             : 
    1260        7788 :         glDisable(GL_POINT_SMOOTH);
    1261        7788 :         glDisable(GL_COLOR_MATERIAL);
    1262        7788 :         glDisable(GL_LIGHTING);
    1263        7788 :         glDisable(GL_BLEND);
    1264        7788 :         glDisable(GL_TEXTURE_2D);
    1265        7788 :         glDisable(GL_CULL_FACE);
    1266        7788 :         glDisable(GL_FOG);
    1267             :         /*Note: we cannot enable/disable normalization on the fly, because we have no clue when the GL implementation
    1268             :         will actually compute the related fragments. Since a typical world always use scaling, we always turn normalization on
    1269             :         to avoid tracking scale*/
    1270        7788 :         glEnable(GL_NORMALIZE);
    1271             : #endif //GLES2
    1272             : 
    1273        7788 :         visual_3d_setup_quality(visual);
    1274             : 
    1275        7788 :         glDisable(GL_BLEND);
    1276        7788 :         glDisable(GL_CULL_FACE);
    1277        7788 :         visual->has_fog = GF_FALSE;
    1278        7788 :         visual->max_lights=GF_MAX_GL_LIGHTS;
    1279        7788 :         visual->max_clips=GF_MAX_GL_CLIPS;
    1280             : 
    1281        7788 :         visual->gl_setup = GF_TRUE;
    1282             : 
    1283        7788 :         glClear(GL_DEPTH_BUFFER_BIT);
    1284             : }
    1285             : 
    1286        9506 : void visual_3d_set_background_state(GF_VisualManager *visual, Bool on)
    1287             : {
    1288             : #ifndef GPAC_USE_GLES2
    1289        9506 :         if (on) {
    1290        4753 :                 glDisable(GL_LIGHTING);
    1291        4753 :                 glDisable(GL_FOG);
    1292        4753 :                 glDisable(GL_LINE_SMOOTH);
    1293             : 
    1294        4753 :                 glDisable(GL_BLEND);
    1295             : #ifndef GPAC_USE_GLES1X
    1296        4753 :                 glDisable(GL_POLYGON_SMOOTH);
    1297             : #endif
    1298        4753 :                 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
    1299        4753 :                 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
    1300             :         } else {
    1301        4753 :                 visual_3d_setup_quality(visual);
    1302             :         }
    1303             : #endif
    1304             : 
    1305             :         visual_3d_enable_depth_buffer(visual, ! on);
    1306        9506 : }
    1307             : 
    1308             : 
    1309             : 
    1310       18728 : void visual_3d_enable_antialias(GF_VisualManager *visual, Bool bOn)
    1311             : {
    1312             : #ifndef GPAC_USE_GLES2
    1313             : 
    1314       18728 :         if (bOn) {
    1315       15027 :                 glEnable(GL_LINE_SMOOTH);
    1316             : #ifndef GPAC_USE_GLES1X
    1317       15027 :                 if (visual->compositor->paa)
    1318           0 :                         glEnable(GL_POLYGON_SMOOTH);
    1319             :                 else
    1320       15027 :                         glDisable(GL_POLYGON_SMOOTH);
    1321             : #endif
    1322             :         } else {
    1323        3701 :                 glDisable(GL_LINE_SMOOTH);
    1324             : #ifndef GPAC_USE_GLES1X
    1325        3701 :                 glDisable(GL_POLYGON_SMOOTH);
    1326             : #endif
    1327             : 
    1328             : /*              glDisable(GL_DITHER);
    1329             :                 glDisable(GL_POINT_SMOOTH);
    1330             :                 glHint(GL_POINT_SMOOTH, GL_DONT_CARE);
    1331             :                 glHint(GL_LINE_SMOOTH, GL_DONT_CARE);
    1332             :                 glHint(GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE);
    1333             :         
    1334             :                 glDisable( GL_MULTISAMPLE_ARB);
    1335             : */
    1336             :         }
    1337             : 
    1338             : #endif
    1339       18728 : }
    1340             : 
    1341        8742 : void visual_3d_enable_depth_buffer(GF_VisualManager *visual, Bool on)
    1342             : {
    1343       18248 :         if (on) {
    1344       11854 :                 glEnable(GL_DEPTH_TEST);
    1345             :         } else {
    1346        6394 :                 glDisable(GL_DEPTH_TEST);
    1347             :         }
    1348        8742 : }
    1349             : 
    1350        9936 : void visual_3d_set_viewport(GF_VisualManager *visual, GF_Rect vp)
    1351             : {
    1352        9936 :         glViewport(FIX2INT(vp.x), FIX2INT(vp.y), FIX2INT(vp.width), FIX2INT(vp.height));
    1353        9936 : }
    1354             : 
    1355        8742 : void visual_3d_set_scissor(GF_VisualManager *visual, GF_Rect *vp)
    1356             : {
    1357             : #ifndef GPAC_USE_TINYGL
    1358        8742 :         if (vp) {
    1359           0 :                 glEnable(GL_SCISSOR_TEST);
    1360           0 :                 glScissor(FIX2INT(vp->x), FIX2INT(vp->y), FIX2INT(vp->width), FIX2INT(vp->height));
    1361             :         } else {
    1362        8742 :                 glDisable(GL_SCISSOR_TEST);
    1363             :         }
    1364             : #endif
    1365        8742 : }
    1366             : 
    1367        1945 : void visual_3d_clear_depth(GF_VisualManager *visual)
    1368             : {
    1369        1945 :         glClear(GL_DEPTH_BUFFER_BIT);
    1370        1945 : }
    1371             : 
    1372      367016 : static void visual_3d_draw_aabb_node(GF_TraverseState *tr_state, GF_Mesh *mesh, u32 prim_type, GF_Plane *fplanes, u32 *p_indices, AABBNode *n, void *idx_addr)
    1373             : {
    1374             :         u32 i;
    1375             : 
    1376             :         /*if not leaf do cull*/
    1377      367016 :         if (n->pos) {
    1378             :                 u32 p_idx, cull;
    1379             :                 SFVec3f vertices[8];
    1380             :                 /*get box vertices*/
    1381      229550 :                 gf_bbox_get_vertices(n->min, n->max, vertices);
    1382             :                 cull = CULL_INSIDE;
    1383     1060798 :                 for (i=0; i<6; i++) {
    1384     1018479 :                         p_idx = p_indices[i];
    1385             :                         /*check p-vertex: if not in plane, we're out (since p-vertex is the closest point to the plane)*/
    1386     1018479 :                         if (gf_plane_get_distance(&fplanes[i], &vertices[p_idx])<0) {
    1387             :                                 cull = CULL_OUTSIDE;
    1388             :                                 break;
    1389             :                         }
    1390             :                         /*check n-vertex: if not in plane, we're intersecting*/
    1391     1011346 :                         if (gf_plane_get_distance(&fplanes[i], &vertices[7-p_idx])<0) {
    1392             :                                 cull = CULL_INTERSECTS;
    1393             :                                 break;
    1394             :                         }
    1395             :                 }
    1396             : 
    1397      416781 :                 if (cull==CULL_OUTSIDE) return;
    1398             : 
    1399      222417 :                 if (cull==CULL_INTERSECTS) {
    1400      180098 :                         visual_3d_draw_aabb_node(tr_state, mesh, prim_type, fplanes, p_indices, n->pos, idx_addr);
    1401      180098 :                         visual_3d_draw_aabb_node(tr_state, mesh, prim_type, fplanes, p_indices, n->neg, idx_addr);
    1402      180098 :                         return;
    1403             :                 }
    1404             :         }
    1405             : 
    1406             :         /*the good thing about the structure of the aabb tree is that the primitive idx is valid for both
    1407             :         leaf and non-leaf nodes, so we can use it as soon as we have a CULL_INSIDE.
    1408             :         However we must push triangles one by one since primitive order may have been swapped when
    1409             :         building the AABB tree*/
    1410     3509026 :         for (i=0; i<n->nb_idx; i++) {
    1411     3509026 :                 u32 idx = 3*n->indices[i];
    1412             :                 void *vbi_addr;
    1413     3509026 :                 if (!idx_addr) vbi_addr = (void *) PTR_TO_U_CAST ( sizeof(IDX_TYPE) * idx );
    1414           0 :                 else vbi_addr = &mesh->indices[idx];
    1415             : 
    1416             : #if defined(GPAC_USE_GLES1X) || defined(GPAC_USE_GLES2)
    1417             :                 glDrawElements(prim_type, 3, GL_UNSIGNED_SHORT, vbi_addr);
    1418             : #else
    1419     3509026 :                 glDrawElements(prim_type, 3, GL_UNSIGNED_INT, vbi_addr);
    1420             : #endif
    1421             :         }
    1422             : }
    1423             : 
    1424             : #ifndef GPAC_USE_GLES2
    1425             : 
    1426             : static void visual_3d_matrix_load(GF_VisualManager *visual, Fixed *mat)
    1427             : {
    1428             : #if defined(GPAC_FIXED_POINT)
    1429             :         Float _mat[16];
    1430             :         u32 i;
    1431             : #endif
    1432             : 
    1433         314 :         if (!mat) {
    1434           0 :                 glLoadIdentity();
    1435             :                 return;
    1436             :         }
    1437             : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
    1438             :         glLoadMatrixx(mat);
    1439             : #elif defined(GPAC_FIXED_POINT)
    1440             :         for (i=0; i<16; i++) _mat[i] = FIX2FLT(mat[i]);
    1441             :         glLoadMatrixf(_mat);
    1442             : #else
    1443         784 :         glLoadMatrixf(mat);
    1444             : #endif
    1445             : }
    1446             : 
    1447         316 : static void visual_3d_update_matrices(GF_TraverseState *tr_state)
    1448             : {
    1449             :         GF_Matrix mx;
    1450         316 :         if (!tr_state || !tr_state->camera) return;
    1451         316 :         if (tr_state->visual->needs_projection_matrix_reload) {
    1452         314 :                 tr_state->visual->needs_projection_matrix_reload = 0;
    1453         314 :                 glMatrixMode(GL_PROJECTION);
    1454         314 :                 visual_3d_matrix_load(tr_state->visual, tr_state->camera->projection.m);
    1455         314 :                 glMatrixMode(GL_MODELVIEW);
    1456             :         }
    1457             : 
    1458         316 :         gf_mx_copy(mx, tr_state->camera->modelview.m);
    1459         316 :         gf_mx_add_matrix(&mx, &tr_state->model_matrix);
    1460             :         visual_3d_matrix_load(tr_state->visual, (Fixed *) &mx);
    1461             : }
    1462             : 
    1463             : 
    1464         164 : static void visual_3d_set_clippers(GF_VisualManager *visual, GF_TraverseState *tr_state)
    1465             : {
    1466             : #ifdef GL_MAX_CLIP_PLANES
    1467             :         u32 i;
    1468             :         GF_Matrix inv_mx;
    1469             : 
    1470         164 :         if (!visual->num_clips)
    1471         164 :                 return;
    1472             : 
    1473           0 :         gf_mx_copy(inv_mx, tr_state->model_matrix);
    1474           0 :         gf_mx_inverse(&inv_mx);
    1475             : 
    1476           0 :         for (i=0; i<visual->num_clips; i++) {
    1477           0 :                 u32 idx = GL_CLIP_PLANE0 + i;
    1478             : #ifdef GPAC_USE_GLES1X
    1479             :                 Fixed g[4];
    1480             : #else
    1481             :                 Double g[4];
    1482             : #endif
    1483             :                 GF_Matrix mx;
    1484           0 :                 GF_Plane p = visual->clippers[i].p;
    1485             : 
    1486           0 :                 if (visual->clippers[i].is_2d_clip) {
    1487           0 :                         visual_3d_matrix_load(tr_state->visual, tr_state->camera->modelview.m);
    1488             :                 } else {
    1489             :                         gf_mx_copy(mx, inv_mx);
    1490           0 :                         if (visual->clippers[i].mx_clipper != NULL) {
    1491           0 :                                 gf_mx_add_matrix(&mx, visual->clippers[i].mx_clipper);
    1492             :                         }
    1493           0 :                         gf_mx_apply_plane(&mx, &p);
    1494             :                 }
    1495             : 
    1496             : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
    1497             :                 g[0] = p.normal.x;
    1498             :                 g[1] = p.normal.y;
    1499             :                 g[2] = p.normal.z;
    1500             :                 g[3] = p.d;
    1501             :                 glClipPlanex(idx, g);
    1502             : #else
    1503           0 :                 g[0] = FIX2FLT(p.normal.x);
    1504           0 :                 g[1] = FIX2FLT(p.normal.y);
    1505           0 :                 g[2] = FIX2FLT(p.normal.z);
    1506           0 :                 g[3] = FIX2FLT(p.d);
    1507             : 
    1508             : #if defined(GPAC_USE_GLES1X)
    1509             :                 glClipPlanef(idx, g);
    1510             : #else
    1511           0 :                 glClipPlane(idx, g);
    1512             : #endif
    1513             : 
    1514             : #endif
    1515           0 :                 glEnable(idx);
    1516             : 
    1517           0 :                 if (visual->clippers[i].is_2d_clip) {
    1518           0 :                         visual_3d_update_matrices(tr_state);
    1519             :                 }
    1520             : 
    1521             :         }
    1522             : #endif
    1523             : 
    1524             : }
    1525             : 
    1526             : static void visual_3d_reset_clippers(GF_VisualManager *visual)
    1527             : {
    1528             : #ifdef GL_MAX_CLIP_PLANES
    1529             :         u32 i;
    1530           0 :         for (i=0; i<visual->num_clips; i++) {
    1531           0 :                 glDisable(GL_CLIP_PLANE0 + i);
    1532             :         }
    1533             : #endif
    1534             : }
    1535             : 
    1536             : 
    1537         164 : void visual_3d_reset_lights(GF_VisualManager *visual)
    1538             : {
    1539             :         u32 i;
    1540         164 :         if (!visual->num_lights) return;
    1541         152 :         for (i=0; i<visual->num_lights; i++) {
    1542         152 :                 glDisable(GL_LIGHT0 + i);
    1543             :         }
    1544         152 :         glDisable(GL_LIGHTING);
    1545             : }
    1546             : 
    1547             : 
    1548         164 : static void visual_3d_set_lights(GF_VisualManager *visual)
    1549             : {
    1550             :         u32 i;
    1551             : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
    1552             :         Fixed vals[4], exp;
    1553             : #else
    1554             :         Float vals[4], intensity, cutOffAngle, beamWidth, ambientIntensity, exp;
    1555             : #endif
    1556             : 
    1557         176 :         if (!visual->num_lights) return;
    1558             : 
    1559         152 :         for (i=0; i<visual->num_lights; i++) {
    1560             :                 GF_Matrix mx;
    1561             :                 GF_LightInfo *li = &visual->lights[i];
    1562         152 :                 GLint iLight = GL_LIGHT0 + i;
    1563         152 :                 if(li->type==3) {
    1564         152 :                         gf_mx_init(mx);
    1565             :                 } else {
    1566           0 :                         gf_mx_copy(mx, visual->camera.modelview.m);
    1567           0 :                         gf_mx_add_matrix(&mx, &li->light_mx);
    1568             :                 }
    1569             :                 visual_3d_matrix_load(visual, mx.m);
    1570             : 
    1571         152 :                 glEnable(iLight);
    1572             : 
    1573         152 :                 switch (li->type) {
    1574             :                 //directional light
    1575         152 :                 case 0:
    1576             :                 case 3:
    1577             : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
    1578             :                         vals[0] = -li->direction.x;
    1579             :                         vals[1] = -li->direction.y;
    1580             :                         vals[2] = -li->direction.z;
    1581             :                         vals[3] = 0;
    1582             :                         glLightxv(iLight, GL_POSITION, vals);
    1583             :                         vals[0] = gf_mulfix(li->color.red, li->intensity);
    1584             :                         vals[1] = gf_mulfix(li->color.green, li->intensity);
    1585             :                         vals[2] = gf_mulfix(li->color.blue, li->intensity);
    1586             :                         vals[3] = FIX_ONE;
    1587             :                         glLightxv(iLight, GL_DIFFUSE, vals);
    1588             :                         glLightxv(iLight, GL_SPECULAR, vals);
    1589             :                         vals[0] = gf_mulfix(li->color.red, li->ambientIntensity);
    1590             :                         vals[1] = gf_mulfix(li->color.green, li->ambientIntensity);
    1591             :                         vals[2] = gf_mulfix(li->color.blue, li->ambientIntensity);
    1592             :                         vals[3] = FIX_ONE;
    1593             :                         glLightxv(iLight, GL_AMBIENT, vals);
    1594             : 
    1595             :                         glLightx(iLight, GL_CONSTANT_ATTENUATION, FIX_ONE);
    1596             :                         glLightx(iLight, GL_LINEAR_ATTENUATION, 0);
    1597             :                         glLightx(iLight, GL_QUADRATIC_ATTENUATION, 0);
    1598             :                         glLightx(iLight, GL_SPOT_CUTOFF, INT2FIX(180) );
    1599             : #else
    1600         152 :                         ambientIntensity = FIX2FLT(li->ambientIntensity);
    1601         152 :                         intensity = FIX2FLT(li->intensity);
    1602             : 
    1603         152 :                         vals[0] = -FIX2FLT(li->direction.x);
    1604         152 :                         vals[1] = -FIX2FLT(li->direction.y);
    1605         152 :                         vals[2] = -FIX2FLT(li->direction.z);
    1606         152 :                         vals[3] = 0;
    1607         152 :                         glLightfv(iLight, GL_POSITION, vals);
    1608         152 :                         vals[0] = FIX2FLT(li->color.red)*intensity;
    1609         152 :                         vals[1] = FIX2FLT(li->color.green)*intensity;
    1610         152 :                         vals[2] = FIX2FLT(li->color.blue)*intensity;
    1611         152 :                         vals[3] = 1;
    1612         152 :                         glLightfv(iLight, GL_DIFFUSE, vals);
    1613         152 :                         glLightfv(iLight, GL_SPECULAR, vals);
    1614         152 :                         vals[0] = FIX2FLT(li->color.red)*ambientIntensity;
    1615         152 :                         vals[1] = FIX2FLT(li->color.green)*ambientIntensity;
    1616         152 :                         vals[2] = FIX2FLT(li->color.blue)*ambientIntensity;
    1617         152 :                         vals[3] = 1;
    1618         152 :                         glLightfv(iLight, GL_AMBIENT, vals);
    1619             : 
    1620         152 :                         glLightf(iLight, GL_CONSTANT_ATTENUATION, 1.0f);
    1621         152 :                         glLightf(iLight, GL_LINEAR_ATTENUATION, 0);
    1622         152 :                         glLightf(iLight, GL_QUADRATIC_ATTENUATION, 0);
    1623         152 :                         glLightf(iLight, GL_SPOT_CUTOFF, 180);
    1624             : #endif
    1625         152 :                         break;
    1626             : 
    1627             : 
    1628             :                 //spot light
    1629           0 :                 case 1:
    1630             : #ifndef GPAC_USE_GLES1X
    1631           0 :                         ambientIntensity = FIX2FLT(li->ambientIntensity);
    1632           0 :                         intensity = FIX2FLT(li->intensity);
    1633           0 :                         cutOffAngle = FIX2FLT(li->cutOffAngle);
    1634           0 :                         beamWidth = FIX2FLT(li->beamWidth);
    1635             : #endif
    1636             : 
    1637             : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
    1638             :                         vals[0] = li->direction.x;
    1639             :                         vals[1] = li->direction.y;
    1640             :                         vals[2] = li->direction.z;
    1641             :                         vals[3] = FIX_ONE;
    1642             :                         glLightxv(iLight, GL_SPOT_DIRECTION, vals);
    1643             :                         vals[0] = li->position.x;
    1644             :                         vals[1] = li->position.y;
    1645             :                         vals[2] = li->position.z;
    1646             :                         vals[3] = FIX_ONE;
    1647             :                         glLightxv(iLight, GL_POSITION, vals);
    1648             :                         glLightx(iLight, GL_CONSTANT_ATTENUATION, li->attenuation.x ? li->attenuation.x : FIX_ONE);
    1649             :                         glLightx(iLight, GL_LINEAR_ATTENUATION, li->attenuation.y);
    1650             :                         glLightx(iLight, GL_QUADRATIC_ATTENUATION, li->attenuation.z);
    1651             :                         vals[0] = gf_mulfix(li->color.red, li->intensity);
    1652             :                         vals[1] = gf_mulfix(li->color.green, li->intensity);
    1653             :                         vals[2] = gf_mulfix(li->color.blue, li->intensity);
    1654             :                         vals[3] = FIX_ONE;
    1655             :                         glLightxv(iLight, GL_DIFFUSE, vals);
    1656             :                         glLightxv(iLight, GL_SPECULAR, vals);
    1657             :                         vals[0] = gf_mulfix(li->color.red, li->ambientIntensity);
    1658             :                         vals[1] = gf_mulfix(li->color.green, li->ambientIntensity);
    1659             :                         vals[2] = gf_mulfix(li->color.blue, li->ambientIntensity);
    1660             :                         vals[3] = FIX_ONE;
    1661             :                         glLightxv(iLight, GL_AMBIENT, vals);
    1662             : 
    1663             :                         if (!li->beamWidth) exp = FIX_ONE;
    1664             :                         else if (li->beamWidth > li->cutOffAngle) exp = 0;
    1665             :                         else {
    1666             :                                 exp = FIX_ONE - gf_cos(li->beamWidth);
    1667             :                                 if (exp>FIX_ONE) exp = FIX_ONE;
    1668             :                         }
    1669             :                         glLightx(iLight, GL_SPOT_EXPONENT,  exp*128);
    1670             :                         glLightx(iLight, GL_SPOT_CUTOFF, gf_divfix(180*li->cutOffAngle, GF_PI) );
    1671             : #else
    1672           0 :                         vals[0] = FIX2FLT(li->direction.x);
    1673           0 :                         vals[1] = FIX2FLT(li->direction.y);
    1674           0 :                         vals[2] = FIX2FLT(li->direction.z);
    1675           0 :                         vals[3] = 1;
    1676           0 :                         glLightfv(iLight, GL_SPOT_DIRECTION, vals);
    1677           0 :                         vals[0] = FIX2FLT(li->position.x);
    1678           0 :                         vals[1] = FIX2FLT(li->position.y);
    1679           0 :                         vals[2] = FIX2FLT(li->position.z);
    1680           0 :                         vals[3] = 1;
    1681           0 :                         glLightfv(iLight, GL_POSITION, vals);
    1682           0 :                         glLightf(iLight, GL_CONSTANT_ATTENUATION, li->attenuation.x ? FIX2FLT(li->attenuation.x) : 1.0f);
    1683           0 :                         glLightf(iLight, GL_LINEAR_ATTENUATION, FIX2FLT(li->attenuation.y));
    1684           0 :                         glLightf(iLight, GL_QUADRATIC_ATTENUATION, FIX2FLT(li->attenuation.z));
    1685           0 :                         vals[0] = FIX2FLT(li->color.red)*intensity;
    1686           0 :                         vals[1] = FIX2FLT(li->color.green)*intensity;
    1687           0 :                         vals[2] = FIX2FLT(li->color.blue)*intensity;
    1688           0 :                         vals[3] = 1;
    1689           0 :                         glLightfv(iLight, GL_DIFFUSE, vals);
    1690           0 :                         glLightfv(iLight, GL_SPECULAR, vals);
    1691           0 :                         vals[0] = FIX2FLT(li->color.red)*ambientIntensity;
    1692           0 :                         vals[1] = FIX2FLT(li->color.green)*ambientIntensity;
    1693           0 :                         vals[2] = FIX2FLT(li->color.blue)*ambientIntensity;
    1694           0 :                         vals[3] = 1;
    1695           0 :                         glLightfv(iLight, GL_AMBIENT, vals);
    1696             : 
    1697             :                         //glLightf(iLight, GL_SPOT_EXPONENT, 0.5f * (beamWidth+0.001f) /*(Float) (0.5 * log(0.5) / log(cos(beamWidth)) ) */);
    1698           0 :                         if (!beamWidth) exp = 1;
    1699           0 :                         else if (beamWidth>cutOffAngle) exp = 0;
    1700             :                         else {
    1701           0 :                                 exp = 1.0f - (Float) cos(beamWidth);
    1702           0 :                                 if (exp>1) exp = 1;
    1703             :                         }
    1704           0 :                         glLightf(iLight, GL_SPOT_EXPONENT,  exp*128);
    1705           0 :                         glLightf(iLight, GL_SPOT_CUTOFF, 180*cutOffAngle/FIX2FLT(GF_PI));
    1706             : #endif
    1707           0 :                         break;
    1708             : 
    1709             : 
    1710             :                 //point light
    1711           0 :                 case 2:
    1712             : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
    1713             :                         vals[0] = li->position.x;
    1714             :                         vals[1] = li->position.y;
    1715             :                         vals[2] = li->position.z;
    1716             :                         vals[3] = FIX_ONE;
    1717             :                         glLightxv(iLight, GL_POSITION, vals);
    1718             :                         glLightx(iLight, GL_CONSTANT_ATTENUATION, li->attenuation.x ? li->attenuation.x : FIX_ONE);
    1719             :                         glLightx(iLight, GL_LINEAR_ATTENUATION, li->attenuation.y);
    1720             :                         glLightx(iLight, GL_QUADRATIC_ATTENUATION, li->attenuation.z);
    1721             :                         vals[0] = gf_mulfix(li->color.red, li->intensity);
    1722             :                         vals[1] = gf_mulfix(li->color.green, li->intensity);
    1723             :                         vals[2] = gf_mulfix(li->color.blue, li->intensity);
    1724             :                         vals[3] = FIX_ONE;
    1725             :                         glLightxv(iLight, GL_DIFFUSE, vals);
    1726             :                         glLightxv(iLight, GL_SPECULAR, vals);
    1727             :                         vals[0] = gf_mulfix(li->color.red, li->ambientIntensity);
    1728             :                         vals[1] = gf_mulfix(li->color.green, li->ambientIntensity);
    1729             :                         vals[2] = gf_mulfix(li->color.blue, li->ambientIntensity);
    1730             :                         vals[3] = FIX_ONE;
    1731             :                         glLightxv(iLight, GL_AMBIENT, vals);
    1732             : 
    1733             :                         glLightx(iLight, GL_SPOT_EXPONENT, 0);
    1734             :                         glLightx(iLight, GL_SPOT_CUTOFF, INT2FIX(180) );
    1735             : #else
    1736           0 :                         ambientIntensity = FIX2FLT(li->ambientIntensity);
    1737           0 :                         intensity = FIX2FLT(li->intensity);
    1738             : 
    1739           0 :                         vals[0] = FIX2FLT(li->position.x);
    1740           0 :                         vals[1] = FIX2FLT(li->position.y);
    1741           0 :                         vals[2] = FIX2FLT(li->position.z);
    1742           0 :                         vals[3] = 1;
    1743           0 :                         glLightfv(iLight, GL_POSITION, vals);
    1744           0 :                         glLightf(iLight, GL_CONSTANT_ATTENUATION, li->attenuation.x ? FIX2FLT(li->attenuation.x) : 1.0f);
    1745           0 :                         glLightf(iLight, GL_LINEAR_ATTENUATION, FIX2FLT(li->attenuation.y));
    1746           0 :                         glLightf(iLight, GL_QUADRATIC_ATTENUATION, FIX2FLT(li->attenuation.z));
    1747           0 :                         vals[0] = FIX2FLT(li->color.red)*intensity;
    1748           0 :                         vals[1] = FIX2FLT(li->color.green)*intensity;
    1749           0 :                         vals[2] = FIX2FLT(li->color.blue)*intensity;
    1750           0 :                         vals[3] = 1;
    1751           0 :                         glLightfv(iLight, GL_DIFFUSE, vals);
    1752           0 :                         glLightfv(iLight, GL_SPECULAR, vals);
    1753           0 :                         vals[0] = FIX2FLT(li->color.red)*ambientIntensity;
    1754           0 :                         vals[1] = FIX2FLT(li->color.green)*ambientIntensity;
    1755           0 :                         vals[2] = FIX2FLT(li->color.blue)*ambientIntensity;
    1756           0 :                         vals[3] = 1;
    1757           0 :                         glLightfv(iLight, GL_AMBIENT, vals);
    1758             : 
    1759           0 :                         glLightf(iLight, GL_SPOT_EXPONENT, 0);
    1760           0 :                         glLightf(iLight, GL_SPOT_CUTOFF, 180);
    1761             : #endif
    1762           0 :                         break;
    1763             :                 }
    1764             :         }
    1765             : 
    1766         152 :         glEnable(GL_LIGHTING);
    1767             : 
    1768             : }
    1769             : 
    1770         151 : void visual_3d_enable_fog(GF_VisualManager *visual)
    1771             : {
    1772             : 
    1773             : #ifndef GPAC_USE_TINYGL
    1774             : 
    1775             : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
    1776             :         Fixed vals[4];
    1777             :         glEnable(GL_FOG);
    1778             :         if (!visual->fog_type) glFogx(GL_FOG_MODE, GL_LINEAR);
    1779             :         else if (visual->fog_type==1) glFogx(GL_FOG_MODE, GL_EXP);
    1780             :         else if (visual->fog_type==2) glFogx(GL_FOG_MODE, GL_EXP2);
    1781             :         glFogx(GL_FOG_DENSITY, visual->fog_density);
    1782             :         glFogx(GL_FOG_START, 0);
    1783             :         glFogx(GL_FOG_END, visual->fog_visibility);
    1784             :         vals[0] = visual->fog_color.red;
    1785             :         vals[1] = visual->fog_color.green;
    1786             :         vals[2] = visual->fog_color.blue;
    1787             :         vals[3] = FIX_ONE;
    1788             :         glFogxv(GL_FOG_COLOR, vals);
    1789             :         glHint(GL_FOG_HINT, visual->compositor->fast ? GL_FASTEST : GL_NICEST);
    1790             : #else
    1791             :         Float vals[4];
    1792         151 :         glEnable(GL_FOG);
    1793             : 
    1794             : #if defined(GPAC_USE_GLES1X)
    1795             :         if (!visual->fog_type) glFogf(GL_FOG_MODE, GL_LINEAR);
    1796             :         else if (visual->fog_type==1) glFogf(GL_FOG_MODE, GL_EXP);
    1797             :         else if (visual->fog_type==2) glFogf(GL_FOG_MODE, GL_EXP2);
    1798             : #else
    1799         151 :         if (!visual->fog_type) glFogi(GL_FOG_MODE, GL_LINEAR);
    1800           0 :         else if (visual->fog_type==1) glFogi(GL_FOG_MODE, GL_EXP);
    1801           0 :         else if (visual->fog_type==2) glFogi(GL_FOG_MODE, GL_EXP2);
    1802             : #endif
    1803             : 
    1804         151 :         glFogf(GL_FOG_DENSITY, FIX2FLT(visual->fog_density));
    1805         151 :         glFogf(GL_FOG_START, 0);
    1806         151 :         glFogf(GL_FOG_END, FIX2FLT(visual->fog_visibility));
    1807         151 :         vals[0] = FIX2FLT(visual->fog_color.red);
    1808         151 :         vals[1] = FIX2FLT(visual->fog_color.green);
    1809         151 :         vals[2] = FIX2FLT(visual->fog_color.blue);
    1810         151 :         vals[3] = 1;
    1811         151 :         glFogfv(GL_FOG_COLOR, vals);
    1812         151 :         glHint(GL_FOG_HINT, visual->compositor->fast ? GL_FASTEST : GL_NICEST);
    1813             : #endif
    1814             : 
    1815             : #endif
    1816             : 
    1817         151 : }
    1818             : 
    1819             : #endif // ! GPAC_USE_GLES2
    1820             : 
    1821             : 
    1822       63607 : static void visual_3d_do_draw_mesh(GF_TraverseState *tr_state, GF_Mesh *mesh)
    1823             : {
    1824             :         u32 prim_type;
    1825             :         GF_Matrix mx;
    1826             :         u32 i, p_idx[6];
    1827             :         void *idx_addr = NULL;
    1828             :         GF_Plane fplanes[6];
    1829             : 
    1830             : 
    1831       63607 :         switch (mesh->mesh_type) {
    1832             :         case MESH_LINESET:
    1833             :                 prim_type = GL_LINES;
    1834             :                 break;
    1835         282 :         case MESH_POINTSET:
    1836             :                 prim_type = GL_POINTS;
    1837         282 :                 break;
    1838       28238 :         default:
    1839             :                 prim_type = GL_TRIANGLES;
    1840       28238 :                 break;
    1841             :         }
    1842             : 
    1843       63607 :         if (mesh->vbo_idx) {
    1844       53238 :                 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->vbo_idx);
    1845             :         } else {
    1846       10369 :                 idx_addr = mesh->indices;
    1847             :         }
    1848             : 
    1849             : 
    1850             :         /*if inside or no aabb for the mesh draw vertex array*/
    1851       63607 :         if (!tr_state->visual->compositor->cull || (tr_state->cull_flag==CULL_INSIDE) || !mesh->aabb_root || !mesh->aabb_root->pos)        {
    1852             : #if defined(GPAC_USE_GLES1X) || defined(GPAC_USE_GLES2)
    1853             :                 glDrawElements(prim_type, mesh->i_count, GL_UNSIGNED_SHORT, idx_addr);
    1854             : #else
    1855       60197 :                 glDrawElements(prim_type, mesh->i_count, GL_UNSIGNED_INT, idx_addr);
    1856             : #endif
    1857             : 
    1858             :         } else {
    1859             : 
    1860             :                 /*otherwise cull aabb against frustum - after some testing it appears (as usual) that there must
    1861             :                  be a compromise: we're slowing down the compositor here, however the gain is really appreciable for
    1862             :                  large meshes, especially terrains/elevation grids*/
    1863             : 
    1864             :                 /*first get transformed frustum in local space*/
    1865        3410 :                 gf_mx_copy(mx, tr_state->model_matrix);
    1866        3410 :                 gf_mx_inverse(&mx);
    1867       23870 :                 for (i=0; i<6; i++) {
    1868       20460 :                         fplanes[i] = tr_state->camera->planes[i];
    1869       20460 :                         gf_mx_apply_plane(&mx, &fplanes[i]);
    1870       20460 :                         p_idx[i] = gf_plane_get_p_vertex_idx(&fplanes[i]);
    1871             :                 }
    1872             :                 /*then recursively cull & draw AABB tree*/
    1873        3410 :                 visual_3d_draw_aabb_node(tr_state, mesh, prim_type, fplanes, p_idx, mesh->aabb_root->pos, idx_addr);
    1874        3410 :                 visual_3d_draw_aabb_node(tr_state, mesh, prim_type, fplanes, p_idx, mesh->aabb_root->neg, idx_addr);
    1875             :         }
    1876             : 
    1877       63607 :         if (mesh->vbo_idx) {
    1878       53238 :                 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    1879             :         }
    1880       63607 : }
    1881             : 
    1882       63607 : static Bool visual_3d_bind_buffer(GF_Compositor *compositor, GF_Mesh *mesh, void **base_address)
    1883             : {
    1884       63607 :         *base_address = NULL;
    1885       63607 :         if ((compositor->reset_graphics==2) && mesh->vbo) {
    1886             :                 /*we lost OpenGL context at previous frame, recreate VBO*/
    1887           0 :                 mesh->vbo = 0;
    1888           0 :                 mesh->vbo_idx = 0;
    1889             :         }
    1890             :         /*rebuild VBO for large ojects only (we basically filter quads out)*/
    1891       63607 :         if (!mesh->vbo && compositor->gl_caps.vbo
    1892             : #ifndef GPAC_USE_GLES2
    1893       11667 :                 && (mesh->v_count>4)
    1894             : #endif
    1895             :            ) {
    1896        1298 :                 glGenBuffers(1, &mesh->vbo);
    1897        1298 :                 if (mesh->vbo) {
    1898        1298 :                         glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
    1899        1298 :                         glBufferData(GL_ARRAY_BUFFER, mesh->v_count * sizeof(GF_Vertex) , mesh->vertices, (mesh->vbo_dynamic) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
    1900        1298 :                         mesh->vbo_dirty = 0;
    1901             :                 } else {
    1902             :                         return GF_FALSE;
    1903             :                 }
    1904             : 
    1905        1298 :                 glGenBuffers(1, &mesh->vbo_idx);
    1906        1298 :                 if (mesh->vbo_idx) {
    1907        1298 :                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->vbo_idx);
    1908        1298 :                         glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh->i_count*sizeof(IDX_TYPE), mesh->indices, (mesh->vbo_dynamic) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
    1909             :                 } else {
    1910             :                         return GF_FALSE;
    1911             :                 }
    1912             :         }
    1913             : 
    1914       63607 :         if (mesh->vbo) {
    1915       53238 :                 *base_address = NULL;
    1916       53238 :                 glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
    1917             :         } else {
    1918       10369 :                 *base_address = &mesh->vertices[0].pos;
    1919             :         }
    1920             : 
    1921       63607 :         if (mesh->vbo_dirty) {
    1922           0 :                 glBufferSubData(GL_ARRAY_BUFFER, 0, mesh->v_count * sizeof(GF_Vertex) , mesh->vertices);
    1923             : 
    1924           0 :                 if (mesh->vbo_idx) {
    1925           0 :                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->vbo_idx);
    1926           0 :                         glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh->i_count*sizeof(IDX_TYPE), mesh->indices, (mesh->vbo_dynamic) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
    1927             : 
    1928           0 :                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    1929             :                 }
    1930             : 
    1931           0 :                 mesh->vbo_dirty = 0;
    1932             :         }
    1933             :         return GF_TRUE;
    1934             : }
    1935             : 
    1936             : 
    1937             : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
    1938             : 
    1939       63443 : static void visual_3d_update_matrices_shaders(GF_TraverseState *tr_state)
    1940             : {
    1941             :         GF_Matrix mx;
    1942             : 
    1943       63443 :         if (tr_state->visual->needs_projection_matrix_reload) {
    1944       18096 :                 tr_state->visual->needs_projection_matrix_reload = 0;
    1945       18096 :                 visual_3d_load_matrix_shaders(tr_state->visual->glsl_program, (Fixed *) tr_state->camera->projection.m, "gfProjectionMatrix");
    1946             :         }
    1947             : 
    1948             :         //calculate ModelView matix (camera.view * model)
    1949       63443 :         gf_mx_copy(mx, tr_state->camera->modelview);
    1950       63443 :         gf_mx_add_matrix(&mx, &tr_state->model_matrix);
    1951       63443 :         visual_3d_load_matrix_shaders(tr_state->visual->glsl_program, (Fixed *) &mx.m, "gfModelViewMatrix");
    1952       63443 : }
    1953             : 
    1954       13235 : static void visual_3d_set_lights_shaders(GF_TraverseState *tr_state)
    1955             : {
    1956             :         u32 i;
    1957             :         GF_LightInfo *li;
    1958             :         GF_Vec pt;
    1959             :         Float ambientIntensity, intensity, vals[4];
    1960             :         GLint loc;
    1961             :         GF_Matrix mx;
    1962       13235 :         GF_VisualManager *visual = tr_state->visual;
    1963             :         char szName[100];
    1964             : 
    1965       13235 :         loc = glGetUniformLocation(visual->glsl_program, "gfNumLights");
    1966       13235 :         if (loc>=0)
    1967       13235 :                 glUniform1i(loc, visual->num_lights);
    1968             :         GL_CHECK_ERR()
    1969             : 
    1970             :         /*
    1971             :          * Equivalent to glLightModel(GL_LIGHTMODEL_TWO_SIDE, GL_TRUE);
    1972             :          */
    1973       13235 :         loc = glGetUniformLocation(visual->glsl_program, "gfLightTwoSide");
    1974       13235 :         if (loc>=0)
    1975       13235 :                 glUniform1i(loc, 1);
    1976             :         GL_CHECK_ERR()
    1977             : 
    1978       13235 :         li = &visual->lights[0];
    1979             : 
    1980       13235 :         pt = li->direction;
    1981       13235 :         gf_vec_norm(&pt);
    1982       13235 :         vals[0] = -FIX2FLT(pt.x);
    1983       13235 :         vals[1] = -FIX2FLT(pt.y);
    1984       13235 :         vals[2] = -FIX2FLT(pt.z);
    1985       13235 :         vals[3] = 0;
    1986             : 
    1987       13235 :         ambientIntensity = FIX2FLT(li->ambientIntensity);
    1988       13235 :         intensity = FIX2FLT(li->intensity);
    1989             : 
    1990       13265 :         for (i = 0; i < (int) visual->num_lights; i++) {
    1991             :                 GF_Vec orig;
    1992       13265 :                 li = &visual->lights[i];
    1993             : 
    1994       13265 :                 if (li->type==3) {   //we have a headlight
    1995       10392 :                         gf_mx_init(mx);
    1996             :                 } else {
    1997             :                         //update mx according to the light mx
    1998        2873 :                         gf_mx_copy(mx, visual->camera.modelview);
    1999        2873 :                         gf_mx_add_matrix(&mx, &li->light_mx);
    2000             :                 }
    2001             : 
    2002             :                 sprintf(szName, "%s%d%s", "lights[", i, "].type");
    2003       13265 :                 loc = glGetUniformLocation(visual->glsl_program, szName);            //Uniform name lights[i].type
    2004       13265 :                 if (loc>=0) {
    2005       13265 :                         if (li->type==3) {
    2006       10392 :                                 glUniform1i(loc, 0); //headlight; Set type 0-directional
    2007             :                         } else {
    2008        2873 :                                 glUniform1i(loc, (GLint) li->type); //Set type 0-directional 1-spot 2-point
    2009             :                         }
    2010             :                 }
    2011             : 
    2012             :                 //set for light direction (assuming origin = 0,0,0)
    2013       13265 :                 pt = li->direction;
    2014       13265 :                 orig.x = orig.y = orig.z = 0;
    2015       13265 :                 gf_mx_apply_vec(&mx, &pt);
    2016       13265 :                 gf_mx_apply_vec(&mx, &orig);
    2017       13265 :                 gf_vec_diff(pt, pt, orig);
    2018       13265 :                 gf_vec_norm(&pt);
    2019             : 
    2020       13265 :                 vals[0] = -FIX2FLT(pt.x);
    2021       13265 :                 vals[1] = -FIX2FLT(pt.y);
    2022       13265 :                 vals[2] = -FIX2FLT(pt.z);
    2023       13265 :                 vals[3] = 0;
    2024             :                 sprintf(szName, "%s%d%s", "lights[", i, "].direction");
    2025       13265 :                 loc = glGetUniformLocation(visual->glsl_program, szName);
    2026       13265 :                 if (loc>=0)
    2027       13265 :                         glUniform4fv(loc, 1, vals); //Set direction
    2028             : 
    2029       13265 :                 if ((li->type==0) || (li->type==3) ) {
    2030       10547 :                         pt = li->direction;
    2031       10547 :                         vals[0] = -FIX2FLT(pt.x);
    2032       10547 :                         vals[1] = -FIX2FLT(pt.y);
    2033       10547 :                         vals[2] = -FIX2FLT(pt.z);
    2034       10547 :                         vals[3] = 0;
    2035             :                 } else {        //we have a spot or point light
    2036        2718 :                         pt = li->position;
    2037        2718 :                         gf_mx_apply_vec(&mx, &pt);
    2038        2718 :                         vals[0] = FIX2FLT(pt.x);
    2039        2718 :                         vals[1] = FIX2FLT(pt.y);
    2040        2718 :                         vals[2] = FIX2FLT(pt.z);
    2041        2718 :                         vals[3] = 1.0;
    2042             :                 }
    2043             :                 sprintf(szName, "%s%d%s", "lights[", i, "].position");
    2044       13265 :                 loc = glGetUniformLocation(visual->glsl_program, szName);
    2045       13265 :                 if (loc>=0)
    2046       13265 :                         glUniform4fv(loc, 1, vals);
    2047             : 
    2048       13265 :                 pt = li->attenuation;
    2049       13265 :                 if (li->type && !li->attenuation.x) {
    2050       10392 :                         vals[0]=1.0;
    2051             :                 } else {
    2052        2873 :                         vals[0] = FIX2FLT(pt.x);
    2053             :                 }
    2054       13265 :                 vals[1] = FIX2FLT(pt.y);
    2055       13265 :                 vals[2] = FIX2FLT(pt.z);
    2056             :                 sprintf(szName, "%s%d%s", "lights[", i, "].attenuation");
    2057       13265 :                 loc = glGetUniformLocation(visual->glsl_program, szName);
    2058       13265 :                 if (loc>=0)
    2059       13265 :                         glUniform3fv(loc, 1, vals);
    2060             : 
    2061       13265 :                 vals[0] = FIX2FLT(li->color.red);
    2062       13265 :                 vals[1] = FIX2FLT(li->color.green);
    2063       13265 :                 vals[2] = FIX2FLT(li->color.blue);
    2064       13265 :                 vals[3] = 0;
    2065             :                 sprintf(szName, "%s%d%s", "lights[", i, "].color");
    2066       13265 :                 loc = glGetUniformLocation(visual->glsl_program, szName);
    2067       13265 :                 if (loc>=0)
    2068       13265 :                         glUniform4fv(loc, 1, vals);
    2069             : 
    2070             :                 sprintf(szName, "%s%d%s", "lights[", i, "].intensity");
    2071       13265 :                 loc = glGetUniformLocation(visual->glsl_program, szName);
    2072       13265 :                 if (loc>=0)
    2073       13265 :                         glUniform1f(loc, li->intensity);
    2074             : 
    2075             :                 sprintf(szName, "%s%d%s", "lights[", i, "].cutOffAngle");
    2076       13265 :                 loc = glGetUniformLocation(visual->glsl_program, szName);
    2077       13265 :                 if (loc>=0)
    2078       13265 :                         glUniform1f(loc, li->cutOffAngle);
    2079             : 
    2080             :         }
    2081             : 
    2082             : 
    2083       13235 :         vals[0] = FIX2FLT(li->color.red)*intensity;
    2084       13235 :         vals[1] = FIX2FLT(li->color.green)*intensity;
    2085       13235 :         vals[2] = FIX2FLT(li->color.blue)*intensity;
    2086       13235 :         vals[3] = 1;
    2087       13235 :         loc = glGetUniformLocation(visual->glsl_program, "gfLightDiffuse");
    2088       13235 :         if (loc>=0) glUniform4fv(loc, 1, vals);
    2089             : 
    2090       13235 :         loc = glGetUniformLocation(visual->glsl_program, "gfLightSpecular");
    2091       13235 :         if (loc>=0) glUniform4fv(loc, 1, vals);
    2092             : 
    2093       13235 :         vals[0] = FIX2FLT(li->color.red)*ambientIntensity;
    2094       13235 :         vals[1] = FIX2FLT(li->color.green)*ambientIntensity;
    2095       13235 :         vals[2] = FIX2FLT(li->color.blue)*ambientIntensity;
    2096       13235 :         vals[3] = 1;
    2097       13235 :         loc = glGetUniformLocation(visual->glsl_program, "gfLightAmbient");
    2098       13235 :         if (loc>=0) glUniform4fv(loc, 1, vals);
    2099             : 
    2100             :         GL_CHECK_ERR()
    2101       13235 : }
    2102             : 
    2103       13235 : static void visual_3d_set_fog_shaders(GF_VisualManager *visual)
    2104             : {
    2105             :         GLint loc;
    2106       13235 :         if (visual->has_fog) {
    2107        1021 :                 loc = glGetUniformLocation(visual->glsl_program, "gfFogEnabled");
    2108        1021 :                 if(loc>=0)
    2109        1021 :                         glUniform1i(loc, GL_TRUE);
    2110             : 
    2111        1021 :                 loc = glGetUniformLocation(visual->glsl_program, "gfFogColor");
    2112        1021 :                 if(loc>=0)
    2113        1021 :                         glUniform3fv(loc, 1, (GLfloat *) &visual->fog_color);
    2114             : 
    2115        1021 :                 loc = glGetUniformLocation(visual->glsl_program, "gfFogDensity");
    2116        1021 :                 if(loc>=0)
    2117        1021 :                         glUniform1f(loc, visual->fog_density );
    2118             : 
    2119        1021 :                 loc = glGetUniformLocation(visual->glsl_program, "gfFogType");
    2120        1021 :                 if(loc>=0)
    2121        1021 :                         glUniform1i(loc, (GLuint) visual->fog_type );
    2122             : 
    2123        1021 :                 loc = glGetUniformLocation(visual->glsl_program, "gfFogVisibility");
    2124        1021 :                 if(loc>=0)
    2125        1021 :                         glUniform1f(loc, visual->fog_visibility);
    2126             :         } else {
    2127       12214 :                 loc = glGetUniformLocation(visual->glsl_program, "gfFogEnabled");
    2128       12214 :                 if(loc>=0)
    2129       12214 :                         glUniform1i(loc, GL_FALSE);
    2130             : 
    2131             :         }
    2132             :         GL_CHECK_ERR()
    2133       13235 : }
    2134             : 
    2135       63443 : static void visual_3d_set_clippers_shaders(GF_VisualManager *visual, GF_TraverseState *tr_state)
    2136             : {
    2137             :         Fixed vals[4];
    2138             :         char szName[100];
    2139             :         GLint loc;
    2140             :         u32 i;
    2141             :         GF_Matrix inv_mx, eye_mx;
    2142             : 
    2143      126587 :         if (!visual->num_clips) return;
    2144             : 
    2145         299 :         gf_mx_copy(inv_mx, tr_state->model_matrix);
    2146         299 :         gf_mx_inverse(&inv_mx);
    2147             : 
    2148         299 :         gf_mx_copy(eye_mx, tr_state->camera->modelview);
    2149         299 :         gf_mx_add_matrix(&eye_mx, &tr_state->model_matrix);
    2150             : 
    2151         299 :         loc = glGetUniformLocation(visual->glsl_program, "gfNumClippers");
    2152         299 :         if (loc>=0)
    2153         299 :                 glUniform1i(loc, visual->num_clips);
    2154             : 
    2155         299 :         for (i = 0; i < visual->num_clips; i++) {
    2156             :                 GF_Matrix mx;
    2157             :                 GF_Plane p;
    2158             : 
    2159         299 :                 p = visual->clippers[i].p;
    2160             :                 //compute clip plane in eye coordinates
    2161         299 :                 if (! visual->clippers[i].is_2d_clip) {
    2162             :                         gf_mx_copy(mx, inv_mx);
    2163         299 :                         if (visual->clippers[i].mx_clipper != NULL) {
    2164         299 :                                 gf_mx_add_matrix(&mx, visual->clippers[i].mx_clipper);
    2165             :                         }
    2166             :                         //plane in local coordinates
    2167         299 :                         gf_mx_apply_plane(&mx, &p);
    2168             :                         //plane in eye coordinates
    2169         299 :                         gf_mx_apply_plane(&eye_mx, &p);
    2170             :                 }
    2171             : 
    2172             :                 sprintf(szName, "%s%d%s", "clipPlane[", i, "]");  //parse plane values
    2173         299 :                 loc = glGetUniformLocation(visual->glsl_program, szName);
    2174         299 :                 if (loc>=0) {
    2175         299 :                         vals[0] = p.normal.x;
    2176         299 :                         vals[1] = p.normal.y;
    2177         299 :                         vals[2] = p.normal.z;
    2178         299 :                         vals[3] = p.d;
    2179         299 :                         glUniform4fv(loc, 1, vals); //Set Plane (w = distance)
    2180             :                 }
    2181             :         }
    2182             : }
    2183             : 
    2184       76927 : GF_GLProgInstance *visual_3d_check_program_exists(GF_VisualManager *root_visual, u32 flags, u32 pix_fmt)
    2185             : {
    2186             :         u32 i, count;
    2187             :         GF_GLProgInstance *prog = NULL;
    2188       76927 :         if (root_visual->compositor->shader_mode_disabled)
    2189             :                 return NULL;
    2190             : 
    2191       76925 :         count = gf_list_count(root_visual->compiled_programs);
    2192      148667 :         for (i=0; i<count; i++) {
    2193      148428 :                 prog = gf_list_get(root_visual->compiled_programs, i);
    2194      148428 :                 if ((prog->flags==flags) && (prog->pix_fmt==pix_fmt)) break;
    2195             :                 prog = NULL;
    2196             :         }
    2197             : 
    2198       76925 :         if (!prog) {
    2199         239 :                 prog = visual_3d_build_program(root_visual, flags, pix_fmt);
    2200         239 :                 if (!prog) return NULL;
    2201         239 :                 gf_list_add(root_visual->compiled_programs, prog);
    2202             :         }
    2203             :         return prog;
    2204             : }
    2205             : 
    2206       63443 : static void visual_3d_draw_mesh_shader_only(GF_TraverseState *tr_state, GF_Mesh *mesh)
    2207             : {
    2208             :         void *vertex_buffer_address;
    2209       63443 :         GF_VisualManager *visual = tr_state->visual;
    2210       63443 :         GF_VisualManager *root_visual = visual->compositor->visual;
    2211             :         GLint loc, loc_vertex_array, loc_color_array, loc_normal_array, loc_textcoord_array;
    2212             :         u32 flags;
    2213       63443 :         u32 num_lights = visual->num_lights;
    2214             :         Bool is_debug_bounds = GF_FALSE;
    2215             :         GF_GLProgInstance *prog = NULL;
    2216             : 
    2217       63443 :         flags = root_visual->active_glsl_flags;
    2218             : 
    2219       63443 :         if (!mesh) {
    2220             :                 is_debug_bounds = GF_TRUE;
    2221       34803 :                 mesh = tr_state->visual->compositor->unit_bbox;
    2222             :                 flags = 0;
    2223             :         }
    2224             : 
    2225       63443 :         if (visual->has_material_2d) {
    2226             :                 num_lights = 0;
    2227             :         }
    2228             : 
    2229       63443 :         if (!tr_state->mesh_num_textures && (mesh->flags & MESH_HAS_COLOR)) {
    2230         331 :                 flags |= GF_GL_HAS_COLOR;
    2231         331 :                 visual->has_material_2d = GF_FALSE;
    2232             :         }
    2233       63112 :         else if (tr_state->mesh_num_textures && (mesh->mesh_type==MESH_TRIANGLES) && !(mesh->flags & MESH_NO_TEXTURE)) {
    2234       13385 :                 flags |= GF_GL_HAS_TEXTURE;
    2235             :         } else {
    2236             :                 flags &= ~GF_GL_HAS_TEXTURE;
    2237             :                 flags &= ~GF_GL_IS_YUV;
    2238       49727 :                 flags &= ~GF_GL_IS_ExternalOES;
    2239             : 
    2240             :         }
    2241             : 
    2242       63443 :         if (num_lights && !is_debug_bounds) {
    2243       13235 :                 flags |= GF_GL_HAS_LIGHT;
    2244             :         } else {
    2245       50208 :                 flags &= ~GF_GL_HAS_LIGHT;
    2246             :         }
    2247             : 
    2248       63443 :         if (visual->num_clips) {
    2249         299 :                 flags |= GF_GL_HAS_CLIP;
    2250             :         } else {
    2251       63144 :                 flags &= ~GF_GL_HAS_CLIP;
    2252             :         }
    2253             : 
    2254       63443 :         root_visual->active_glsl_flags = visual->active_glsl_flags = flags;
    2255             : 
    2256       63443 :         prog = visual_3d_check_program_exists(root_visual, flags, root_visual->bound_tx_pix_fmt);
    2257       63443 :         if (!prog) return;
    2258             : 
    2259             :         //check if we are using a different program than last time, if so force matrices updates
    2260       63443 :         if (visual->glsl_program != prog->prog) {
    2261       13900 :                 tr_state->visual->needs_projection_matrix_reload = GF_TRUE;
    2262             :         }
    2263             : 
    2264             :         GL_CHECK_ERR()
    2265       63443 :         visual->glsl_program = prog->prog;
    2266             : 
    2267       63443 :         glUseProgram(visual->glsl_program);
    2268             :         GL_CHECK_ERR()
    2269             : 
    2270       63443 :         if (! visual_3d_bind_buffer(visual->compositor, mesh, &vertex_buffer_address)) {
    2271           0 :                 glUseProgram(0);
    2272           0 :                 return;
    2273             :         }
    2274             : 
    2275       63443 :         if (visual->state_blend_on)
    2276        1749 :                 glEnable(GL_BLEND);
    2277             : 
    2278       63443 :         visual_3d_update_matrices_shaders(tr_state);
    2279             : 
    2280             :         loc_color_array = loc_normal_array = loc_textcoord_array = -1;
    2281             : 
    2282             :         //setup vertext array location (always true)
    2283       63443 :         loc_vertex_array = glGetAttribLocation(visual->glsl_program, "gfVertex");
    2284       63443 :         if (loc_vertex_array<0)
    2285             :                 return;
    2286             : 
    2287       63443 :         glEnableVertexAttribArray(loc_vertex_array);
    2288             :         GL_CHECK_ERR()
    2289             : #if defined(GPAC_FIXED_POINT)
    2290             :         glVertexAttribPointer(loc_vertex_array, 3, GL_FIXED, GL_TRUE, sizeof(GF_Vertex), vertex_buffer_address);
    2291             : #else
    2292       63443 :         glVertexAttribPointer(loc_vertex_array, 3, GL_FLOAT, GL_FALSE, sizeof(GF_Vertex), vertex_buffer_address);
    2293             : #endif
    2294             : 
    2295             :         //setup scissor
    2296       63443 :         visual_3d_set_clipper_scissor(visual, tr_state);
    2297             : 
    2298             :         //setup clippers
    2299       63443 :         visual_3d_set_clippers_shaders(visual, tr_state);
    2300             : 
    2301       63443 :         if (is_debug_bounds) {
    2302             :                 Float cols[4];
    2303       34803 :                 loc = glGetUniformLocation(visual->glsl_program, "gfEmissionColor");
    2304       34803 :                 cols[0] = 1.0f - FIX2FLT(visual->mat_2d.red);
    2305       34803 :                 cols[1] = 1.0f - FIX2FLT(visual->mat_2d.green);
    2306       34803 :                 cols[2] = 1.0f - FIX2FLT(visual->mat_2d.blue);
    2307       34803 :                 cols[3] = 1.0f;
    2308       34803 :                 if (loc>=0)
    2309       34803 :                         glUniform4fv(loc, 1, (GLfloat *) cols);
    2310             :                 GL_CHECK_ERR()
    2311             : 
    2312       34803 :                 loc = glGetUniformLocation(visual->glsl_program, "hasMaterial2D");
    2313       34803 :                 if (loc>=0)
    2314       34803 :                         glUniform1i(loc, 1);
    2315             :                 GL_CHECK_ERR()
    2316             :         }
    2317             :         /* Material2D does not have any lights, color used is "gfEmissionColor" uniform */
    2318       28640 :         else if (visual->has_material_2d) {
    2319             :                 //for YUV manually set alpha
    2320        9994 :                 if (flags & GF_GL_IS_YUV) {
    2321           0 :                         loc = glGetUniformLocation(visual->glsl_program, "alpha");
    2322           0 :                         if(loc>=0)
    2323           0 :                                 glUniform1f(loc, FIX2FLT(visual->mat_2d.alpha));
    2324             :                 }
    2325             :                 //otherwise handle alpha with blend if no texture
    2326        9994 :                 else if (!tr_state->mesh_num_textures) {
    2327        5707 :                         if (visual->mat_2d.alpha < FIX_ONE) {
    2328         480 :                                 glEnable(GL_BLEND);
    2329             :                         } else {
    2330        5227 :                                 glDisable(GL_BLEND);
    2331             :                         }
    2332             :                 }
    2333             : 
    2334        9994 :                 loc = glGetUniformLocation(visual->glsl_program, "gfEmissionColor");
    2335        9994 :                 if (loc>=0)
    2336        9994 :                         glUniform4fv(loc, 1, (GLfloat *) & visual->mat_2d);
    2337             :                 GL_CHECK_ERR()
    2338             : 
    2339        9994 :                 loc = glGetUniformLocation(visual->glsl_program, "hasMaterial2D");
    2340        9994 :                 if (loc>=0)
    2341        9994 :                         glUniform1i(loc, 1);
    2342             :                 GL_CHECK_ERR()
    2343             : 
    2344             :         } else {
    2345             : 
    2346       18646 :                 loc = glGetUniformLocation(visual->glsl_program, "hasMaterial2D");
    2347       18646 :                 if (loc>=0)
    2348       18646 :                         glUniform1i(loc, 0);
    2349             :                 GL_CHECK_ERR()
    2350             : 
    2351             :                 //for YUV manually set alpha
    2352       18646 :                 if (flags & GF_GL_IS_YUV) {
    2353           0 :                         loc = glGetUniformLocation(visual->glsl_program, "alpha");
    2354           0 :                         if(loc>=0)
    2355           0 :                                 glUniform1f(loc, 1.0);
    2356             :                         GL_CHECK_ERR()
    2357             :                 }
    2358             :         }
    2359             : 
    2360             :         /* if lighting is on, setup material */
    2361       63443 :         if ((flags & GF_GL_HAS_LIGHT) && visual->has_material && !visual->has_material_2d) {
    2362             :                 u32 i;
    2363       52940 :                 for(i =0; i<4; i++) {
    2364       52940 :                         Fixed *rgba = (Fixed *) & visual->materials[i];
    2365             : #if defined(GPAC_FIXED_POINT)
    2366             :                         Float _rgba[4];
    2367             :                         _rgba[0] = FIX2FLT(rgba[0]);
    2368             :                         _rgba[1] = FIX2FLT(rgba[1]);
    2369             :                         _rgba[2] = FIX2FLT(rgba[2]);
    2370             :                         _rgba[3] = FIX2FLT(rgba[3]);
    2371             : #elif defined(GPAC_USE_GLES1X)
    2372             :                         Fixed *_rgba = (Fixed *) rgba;
    2373             : #else
    2374             :                         Float *_rgba = (Float *) rgba;
    2375             : #endif
    2376       52940 :                         switch (i) {
    2377       13235 :                         case 0:
    2378       13235 :                                 loc = glGetUniformLocation(visual->glsl_program, "gfAmbientColor");
    2379       13235 :                                 break;
    2380       13235 :                         case 1:
    2381       13235 :                                 loc = glGetUniformLocation(visual->glsl_program, "gfDiffuseColor");
    2382       13235 :                                 break;
    2383       13235 :                         case 2:
    2384       13235 :                                 loc = glGetUniformLocation(visual->glsl_program, "gfSpecularColor");
    2385       13235 :                                 break;
    2386       13235 :                         case 3:
    2387       13235 :                                 loc = glGetUniformLocation(visual->glsl_program, "gfEmissionColor");
    2388       13235 :                                 break;
    2389             :                         }
    2390             : 
    2391       52940 :                         if (loc>=0)
    2392       52940 :                                 glUniform4fv(loc, 1, _rgba);
    2393             :                 }
    2394             :                 //TO CHECK:  if this does not work as it is supposed to, try: visual->shininess * 128
    2395       13235 :                 loc = glGetUniformLocation(visual->glsl_program, "gfShininess");
    2396       13235 :                 if (loc>=0)
    2397       13235 :                         glUniform1f(loc, FIX2FLT(visual->shininess));
    2398             : 
    2399       13235 :                 glDisable(GL_CULL_FACE);        //Enable for performance; if so, check glFrontFace()
    2400             :         }
    2401             : 
    2402             :         //setup mesh color vertex attribute - only available for some shaders
    2403       63443 :         if (!tr_state->mesh_num_textures && (mesh->flags & MESH_HAS_COLOR) && !is_debug_bounds) {
    2404         331 :                 loc_color_array = glGetAttribLocation(visual->glsl_program, "gfMeshColor");
    2405         331 :                 if (loc_color_array >= 0) {
    2406             : 
    2407             :                         //for now colors are 8bit/comp RGB(A), so used GL_UNSIGNED_BYTE and GL_TRUE for normalizing values
    2408         331 :                         if (mesh->flags & MESH_HAS_ALPHA) {
    2409           4 :                                 glEnable(GL_BLEND);
    2410           4 :                                 tr_state->mesh_is_transparent = 1;
    2411           4 :                                 glVertexAttribPointer(loc_color_array, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GF_Vertex), ((char *)vertex_buffer_address + MESH_COLOR_OFFSET));
    2412             :                         } else {
    2413         327 :                                 glVertexAttribPointer(loc_color_array, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GF_Vertex), ((char *)vertex_buffer_address + MESH_COLOR_OFFSET));
    2414             :                         }
    2415         331 :                         glEnableVertexAttribArray(loc_color_array);
    2416             :                 }
    2417             :                 GL_CHECK_ERR()
    2418             :         }
    2419             : 
    2420       63443 :         if (flags & GF_GL_HAS_LIGHT) {
    2421       13235 :                 visual_3d_set_fog_shaders(visual);
    2422             :         }
    2423             : 
    2424             :         //setup mesh normal vertex attribute - only available for some shaders
    2425       63443 :         if (!visual->has_material_2d && num_lights && (mesh->mesh_type==MESH_TRIANGLES) ) {
    2426             :                 GF_Matrix normal_mx;
    2427             :                 assert(flags & GF_GL_HAS_LIGHT);
    2428             : 
    2429       13235 :                 gf_mx_copy(normal_mx, tr_state->camera->modelview);
    2430       13235 :                 gf_mx_add_matrix(&normal_mx, &tr_state->model_matrix);
    2431       13235 :                 normal_mx.m[12] = normal_mx.m[13] = normal_mx.m[14] = 0;
    2432       13235 :                 gf_mx_inverse(&normal_mx);
    2433             : 
    2434             : 
    2435       13235 :                 gf_mx_transpose(&normal_mx);
    2436             : 
    2437       13235 :                 visual_3d_load_matrix_shaders(tr_state->visual->glsl_program, (Fixed *) &normal_mx.m, "gfNormalMatrix");
    2438             : 
    2439       13235 :                 loc_normal_array = glGetAttribLocation(visual->glsl_program, "gfNormal");
    2440       13235 :                 if (loc_normal_array>=0) {
    2441             : #ifdef MESH_USE_FIXED_NORMAL
    2442             :                         glVertexAttribPointer(loc_normal_array, 3, GL_FLOAT, GL_FALSE, sizeof(GF_Vertex),  ((char *)vertex_buffer_address + MESH_NORMAL_OFFSET) );
    2443             : #else
    2444       13235 :                         glVertexAttribPointer(loc_normal_array, 3, GL_BYTE, GL_FALSE, sizeof(GF_Vertex),  ((char *)vertex_buffer_address + MESH_NORMAL_OFFSET) );
    2445             : #endif
    2446       13235 :                         glEnableVertexAttribArray(loc_normal_array);
    2447             :                 }
    2448             :                 GL_CHECK_ERR()
    2449             : 
    2450       13235 :                 loc = glGetUniformLocation(visual->glsl_program, "gfNumLights");
    2451       13235 :                 if (loc>=0)
    2452       13235 :                         glUniform1i(loc, num_lights);
    2453       13235 :                 visual_3d_set_lights_shaders(tr_state);
    2454             :                 GL_CHECK_ERR()
    2455             :         }
    2456             : 
    2457             :         //setup mesh normal vertex attribute - only available for some shaders
    2458       63443 :         if (tr_state->mesh_num_textures && (mesh->mesh_type==MESH_TRIANGLES) && !(mesh->flags & MESH_NO_TEXTURE)) {
    2459       13385 :                 if (visual->has_tx_matrix) {
    2460             :                         //parsing texture matrix
    2461        7648 :                         loc = glGetUniformLocation(visual->glsl_program, "gfTextureMatrix");
    2462        7648 :                         if (loc>=0)
    2463        7648 :                                 glUniformMatrix4fv(loc, 1, GL_FALSE, visual->tx_matrix.m);
    2464             :                         GL_CHECK_ERR()
    2465             : 
    2466        7648 :                         loc = glGetUniformLocation(visual->glsl_program, "hasTextureMatrix");
    2467        7648 :                         if (loc>=0) glUniform1i(loc, 1);
    2468             :                 } else {
    2469        5737 :                         loc = glGetUniformLocation(visual->glsl_program, "hasTextureMatrix");
    2470        5737 :                         if (loc>=0) glUniform1i(loc, 0);
    2471             :                 }
    2472             : 
    2473             :                 //parsing texture coordinates
    2474       13385 :                 loc_textcoord_array = glGetAttribLocation(visual->glsl_program, "gfMultiTexCoord");
    2475       13385 :                 if (loc_textcoord_array>=0) {
    2476       13385 :                         glVertexAttribPointer(loc_textcoord_array, 2, GL_FLOAT, GL_FALSE, sizeof(GF_Vertex), ((char *)vertex_buffer_address + MESH_TEX_OFFSET));
    2477       13385 :                         glEnableVertexAttribArray(loc_textcoord_array);
    2478             :                         GL_CHECK_ERR()
    2479             :                 }
    2480             : 
    2481       13385 :                 if (flags & GF_GL_IS_YUV) {
    2482           0 :                         loc = glGetUniformLocation(visual->glsl_program, "yuvPixelFormat");
    2483           0 :                         if (loc>=0) {
    2484             :                                 int yuv_mode = 0;
    2485           0 :                                 switch (visual->yuv_pixelformat_type) {
    2486           0 :                                 case GF_PIXEL_NV21:
    2487             :                                         yuv_mode = 1;
    2488           0 :                                         break;
    2489           0 :                                 case GF_PIXEL_NV12:
    2490             :                                         yuv_mode = 2;
    2491           0 :                                         break;
    2492             :                                 }
    2493             :                         
    2494           0 :                                 glUniform1i(loc, yuv_mode);
    2495             :                         }
    2496             :                         GL_CHECK_ERR()
    2497             :                 }
    2498             :         }
    2499             : 
    2500             :         //
    2501       63443 :         if (mesh->mesh_type != MESH_TRIANGLES) {
    2502             :                 //According to the spec we should pass a 0,0,1 Normal and disable lights. we just disable lights
    2503       35369 :                 if(flags & GF_GL_HAS_LIGHT) {
    2504           0 :                         loc = glGetUniformLocation(visual->glsl_program, "gfNumLights");
    2505           0 :                         if (loc>=0)  glUniform1i(loc, 0);
    2506             : 
    2507             :                 }
    2508       35369 :                 glDisable(GL_CULL_FACE);
    2509             : 
    2510             : #if !defined(GPAC_USE_TINYGL) && !defined(GL_ES_CL_PROFILE)
    2511       35369 :                 glLineWidth(1.0f);
    2512             : #endif
    2513             : 
    2514             :         } else {
    2515       28074 :                 if (visual->compositor->bcull
    2516       28074 :                         && (!tr_state->mesh_is_transparent || (visual->compositor->bcull ==GF_BACK_CULL_ALPHA) )
    2517       26557 :                         && (mesh->flags & MESH_IS_SOLID)) {
    2518       10647 :                         glEnable(GL_CULL_FACE);
    2519       10647 :                         if (tr_state->reverse_backface) {
    2520           0 :                                 glFrontFace((mesh->flags & MESH_IS_CW) ? GL_CCW : GL_CW);
    2521             :                         } else {
    2522       10647 :                                 glFrontFace((mesh->flags & MESH_IS_CW) ? GL_CW : GL_CCW);
    2523             :                         }
    2524             :                 } else {
    2525       17427 :                         glDisable(GL_CULL_FACE);
    2526             :                 }
    2527             :         }
    2528             : 
    2529             :         GL_CHECK_ERR()
    2530             : 
    2531             :         //We have a Colour Matrix to be applied
    2532       63443 :         if(!tr_state->color_mat.identity) {
    2533             :                 GF_Matrix toBeParsed;   //4x4 RGBA Color Matrix
    2534             :                 Fixed translateV[4];    //Vec4 holding translation property of color_mat
    2535             :                 int row,col;
    2536             : 
    2537         136 :                 gf_mx_init(toBeParsed);
    2538             : 
    2539             :                 //Copy values from Color Matrix
    2540         680 :                 for(row=0; row<4; row++) {
    2541        2176 :                         for(col=0; col<4; col++) {
    2542        2176 :                                 toBeParsed.m[col+(row*4)]=tr_state->color_mat.m[col+(row*5)];
    2543             :                         }
    2544         544 :                         translateV[row] = tr_state->color_mat.m[4+(row*5)];
    2545             :                 }
    2546             : 
    2547             :                 //the rest of the values form the translation vector
    2548         136 :                 loc = glGetUniformLocation(visual->glsl_program, "gfTranslationVector");
    2549         136 :                 if (loc>=0)
    2550         136 :                         glUniform4fv(loc, 1, (GLfloat *) &translateV);
    2551             :                 GL_CHECK_ERR()
    2552             : 
    2553         136 :                 loc = glGetUniformLocation(visual->glsl_program, "hasColorMatrix");
    2554         136 :                 if(loc>=0) glUniform1i(loc, 1);
    2555             : 
    2556         136 :                 loc = glGetUniformLocation(visual->glsl_program, "gfColorMatrix");
    2557         136 :                 if (loc>=0)
    2558         136 :                         glUniformMatrix4fv(loc, 1, GL_FALSE, toBeParsed.m);
    2559             :                 GL_CHECK_ERR()
    2560             :         } else {
    2561       63307 :                 loc = glGetUniformLocation(visual->glsl_program, "hasColorMatrix");
    2562       63307 :                 if(loc>=0) glUniform1i(loc, 0);
    2563             :         }
    2564             : 
    2565             : 
    2566             :         //We have a Colour Key to be applied
    2567       63443 :         if(tr_state->col_key) {
    2568             : 
    2569             :                 Float vals[3];
    2570             :                 Float eightbit = 255;   //used for mapping values between 0.0 and 1.0
    2571             : 
    2572           0 :                 glEnable(GL_BLEND);             //normally we shouldn have to need this, but we do
    2573             : 
    2574           0 :                 loc = glGetUniformLocation(visual->glsl_program, "hasColorKey");
    2575           0 :                 if(loc>=0) glUniform1i(loc, 1);
    2576             : 
    2577           0 :                 vals[0] = tr_state->col_key->r/eightbit;
    2578           0 :                 vals[1] = tr_state->col_key->g/eightbit;
    2579           0 :                 vals[2] = tr_state->col_key->b/eightbit;
    2580             : 
    2581           0 :                 loc = glGetUniformLocation(visual->glsl_program, "gfKeyColor");
    2582           0 :                 if(loc>=0)glUniform3fv(loc, 1, vals);
    2583             : 
    2584           0 :                 loc = glGetUniformLocation(visual->glsl_program, "gfKeyLow");
    2585           0 :                 if(loc>=0) glUniform1f(loc, tr_state->col_key->low/eightbit);
    2586             : 
    2587           0 :                 loc = glGetUniformLocation(visual->glsl_program, "gfKeyHigh");
    2588           0 :                 if(loc>=0) glUniform1f(loc, tr_state->col_key->high/eightbit);
    2589             : 
    2590           0 :                 loc = glGetUniformLocation(visual->glsl_program, "gfKeyAlpha");
    2591           0 :                 if(loc>=0) glUniform1f(loc, tr_state->col_key->alpha/eightbit);
    2592             : 
    2593             :         } else {
    2594       63443 :                 loc = glGetUniformLocation(visual->glsl_program, "hasColorKey");
    2595       63443 :                 if(loc>=0) glUniform1i(loc, 0);
    2596             :         }
    2597             : 
    2598             : 
    2599             : 
    2600             : 
    2601       63443 :         visual_3d_do_draw_mesh(tr_state, mesh);
    2602             : 
    2603             :         GL_CHECK_ERR()
    2604             :         //We drawn, now we Reset
    2605             : 
    2606       63443 :         if (mesh->vbo)
    2607       53086 :                 glBindBuffer(GL_ARRAY_BUFFER, 0);
    2608             : 
    2609       63443 :         if (loc_vertex_array>=0) glDisableVertexAttribArray(loc_vertex_array);
    2610       63443 :         if (loc_color_array>=0) glDisableVertexAttribArray(loc_color_array);
    2611       63443 :         if (loc_normal_array>=0) glDisableVertexAttribArray(loc_normal_array);
    2612       63443 :         if (loc_textcoord_array>=0) glDisableVertexAttribArray(loc_textcoord_array);
    2613             : 
    2614             :         //instead of visual_3d_reset_lights(visual);
    2615       63443 :         if(root_visual->active_glsl_flags & GF_GL_HAS_LIGHT) {
    2616       13235 :                 loc = glGetUniformLocation(visual->glsl_program, "gfNumLights");
    2617       13235 :                 if (loc>=0)  glUniform1i(loc, 0);
    2618             :                 GL_CHECK_ERR()
    2619             :         }
    2620             : 
    2621       63443 :         if (visual->has_clipper_2d) {
    2622        3179 :                 glDisable(GL_SCISSOR_TEST);
    2623             :         }
    2624             : 
    2625       63443 :         visual->has_material_2d = GF_FALSE;
    2626       63443 :         visual->active_glsl_flags = root_visual->active_glsl_flags;
    2627       63443 :         root_visual->active_glsl_flags &= ~ GF_GL_HAS_COLOR;
    2628       63443 :         visual->has_material = 0;
    2629       63443 :         visual->state_color_on = 0;
    2630       63443 :         if (tr_state->mesh_is_transparent) glDisable(GL_BLEND);
    2631       63443 :         tr_state->mesh_is_transparent = 0;
    2632             :         GL_CHECK_ERR()
    2633       63443 :         glUseProgram(0);
    2634             :         GL_CHECK_ERR()
    2635             : }
    2636             : 
    2637             : #endif // !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
    2638             : 
    2639             : //#endif //GPAC_USE_GLES2
    2640             : 
    2641             : 
    2642       63607 : static void visual_3d_draw_mesh(GF_TraverseState *tr_state, GF_Mesh *mesh)
    2643             : {
    2644             : #ifndef GPAC_USE_GLES2
    2645       63607 :         GF_Compositor *compositor = tr_state->visual->compositor;
    2646             :         GF_VisualManager *visual = tr_state->visual;
    2647             :         Bool has_col, has_tx, has_norm;
    2648       63607 :         void *base_address = NULL;
    2649             :         Bool is_debug_bounds = GF_FALSE;
    2650             : 
    2651             : #if defined(GPAC_FIXED_POINT) && !defined(GPAC_USE_GLES1X)
    2652             :         Float *color_array = NULL;
    2653             :         Float fix_scale = 1.0f;
    2654             :         fix_scale /= FIX_ONE;
    2655             : #endif
    2656             : 
    2657             : #endif
    2658             : 
    2659       63607 :         if (mesh) {
    2660       28804 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[V3D] Drawing mesh %p\n", mesh));
    2661             :         }
    2662             : 
    2663             :         //clear error
    2664       63607 :         glGetError();
    2665             :         GL_CHECK_ERR()
    2666             : 
    2667             : #ifdef GPAC_USE_GLES2
    2668             :         visual_3d_draw_mesh_shader_only(tr_state, mesh);
    2669             :         return;
    2670             : #else
    2671             : 
    2672             : #if !defined(GPAC_CONFIG_ANDROID) && !defined(GPAC_CONFIG_IOS) && !defined(GPAC_FIXED_POINT)
    2673       63607 :         if (!visual->compositor->shader_mode_disabled) {
    2674       63443 :                 visual_3d_draw_mesh_shader_only(tr_state, mesh);
    2675       63443 :                 return;
    2676             :         }
    2677             : #endif
    2678             : 
    2679         164 :         if (!mesh) {
    2680           0 :                 mesh = tr_state->visual->compositor->unit_bbox;
    2681             :                 is_debug_bounds = GF_TRUE;
    2682             :         }
    2683             : 
    2684         164 :         if (! visual_3d_bind_buffer(compositor, mesh, &base_address)) {
    2685             : #if! defined(GPAC_USE_GLES1X) && !defined(GPAC_USE_TINYGL)
    2686           0 :                 glUseProgram(0);
    2687             : #endif
    2688           0 :                 return;
    2689             :         }
    2690             :         has_col = has_tx = has_norm = 0;
    2691             : 
    2692         164 :         if (!is_debug_bounds) {
    2693             :                 //set lights before pushing modelview matrix
    2694         164 :                 visual_3d_set_lights(visual);
    2695             :         }
    2696             : 
    2697         164 :         visual_3d_update_matrices(tr_state);
    2698             : 
    2699             :         /*enable states*/
    2700         164 :         if (!is_debug_bounds) {
    2701         164 :                 if (visual->has_fog) visual_3d_enable_fog(visual);
    2702             : 
    2703         164 :                 if (visual->state_color_on) glEnable(GL_COLOR_MATERIAL);
    2704         162 :                 else glDisable(GL_COLOR_MATERIAL);
    2705             : 
    2706         164 :                 if (visual->state_blend_on) glEnable(GL_BLEND);
    2707             :         }
    2708             : 
    2709             : 
    2710             :         //setup scissor
    2711         164 :         visual_3d_set_clipper_scissor(visual, tr_state);
    2712             : 
    2713         164 :         visual_3d_set_clippers(visual, tr_state);
    2714             : 
    2715         164 :         glEnableClientState(GL_VERTEX_ARRAY);
    2716             : #if defined(GPAC_USE_GLES1X)
    2717             :         glVertexPointer(3, GL_FIXED, sizeof(GF_Vertex),  base_address);
    2718             : #elif defined(GPAC_FIXED_POINT)
    2719             :         /*scale modelview matrix*/
    2720             :         glPushMatrix();
    2721             :         glScalef(fix_scale, fix_scale, fix_scale);
    2722             :         glVertexPointer(3, GL_INT, sizeof(GF_Vertex), base_address);
    2723             : #else
    2724         164 :         glVertexPointer(3, GL_FLOAT, sizeof(GF_Vertex), base_address);
    2725             : #endif
    2726             : 
    2727             : 
    2728             :         /*
    2729             :         *       Enable colors:
    2730             :         if mat2d is set, use mat2d and no lighting
    2731             :         */
    2732         164 :         if (visual->has_material_2d) {
    2733          10 :                 glDisable(GL_LIGHTING);
    2734          10 :                 if (visual->mat_2d.alpha != FIX_ONE) {
    2735           0 :                         glEnable(GL_BLEND);
    2736             :                         visual_3d_enable_antialias(visual, 0);
    2737             :                 } else {
    2738             :                         //disable blending only if no texture !
    2739          10 :                         if (!tr_state->mesh_num_textures)
    2740          10 :                                 glDisable(GL_BLEND);
    2741          10 :                         visual_3d_enable_antialias(visual, visual->compositor->aa ? 1 : 0);
    2742             :                 }
    2743             : #ifdef GPAC_USE_GLES1X
    2744             :                 glColor4x( FIX2INT(visual->mat_2d.red * 255), FIX2INT(visual->mat_2d.green * 255), FIX2INT(visual->mat_2d.blue * 255), FIX2INT(visual->mat_2d.alpha * 255));
    2745             : #elif defined(GPAC_FIXED_POINT)
    2746             :                 glColor4f(FIX2FLT(visual->mat_2d.red), FIX2FLT(visual->mat_2d.green), FIX2FLT(visual->mat_2d.blue), FIX2FLT(visual->mat_2d.alpha));
    2747             : #else
    2748          10 :                 glColor4f(visual->mat_2d.red, visual->mat_2d.green, visual->mat_2d.blue, visual->mat_2d.alpha);
    2749             : #endif
    2750             :         }
    2751             : 
    2752             :         //setup material color
    2753         164 :         if (visual->has_material) {
    2754             :                 u32 i;
    2755             :                 GL_CHECK_ERR()
    2756         608 :                 for (i=0; i<4; i++) {
    2757             :                         GLenum mode;
    2758         608 :                         Fixed *rgba = (Fixed *) & visual->materials[i];
    2759             : #if defined(GPAC_USE_GLES1X)
    2760             :                         Fixed *_rgba = (Fixed *) rgba;
    2761             : #elif defined(GPAC_FIXED_POINT)
    2762             :                         Float _rgba[4];
    2763             :                         _rgba[0] = FIX2FLT(rgba[0]);
    2764             :                         _rgba[1] = FIX2FLT(rgba[1]);
    2765             :                         _rgba[2] = FIX2FLT(rgba[2]);
    2766             :                         _rgba[3] = FIX2FLT(rgba[3]);
    2767             : #else
    2768             :                         Float *_rgba = (Float *) rgba;
    2769             : #endif
    2770             : 
    2771             :                         switch (i) {
    2772             :                         case 0:
    2773             :                                 mode = GL_AMBIENT;
    2774             :                                 break;
    2775             :                         case 1:
    2776             :                                 mode = GL_DIFFUSE;
    2777             :                                 break;
    2778             :                         case 2:
    2779             :                                 mode = GL_SPECULAR;
    2780             :                                 break;
    2781             :                         default:
    2782             :                                 mode = GL_EMISSION;
    2783             :                                 break;
    2784             :                         }
    2785             : 
    2786             : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
    2787             :                         glMaterialxv(GL_FRONT_AND_BACK, mode, _rgba);
    2788             : #else
    2789         608 :                         glMaterialfv(GL_FRONT_AND_BACK, mode, _rgba);
    2790             : #endif
    2791             :                         GL_CHECK_ERR()
    2792             :                 }
    2793             : #ifdef GPAC_USE_GLES1X
    2794             :                 glMaterialx(GL_FRONT_AND_BACK, GL_SHININESS, visual->shininess * 128);
    2795             : #else
    2796         152 :                 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, FIX2FLT(visual->shininess) * 128);
    2797             : #endif
    2798             :                 GL_CHECK_ERR()
    2799             :         }
    2800             : 
    2801             :         //otherwise setup mesh color
    2802         164 :         if (!tr_state->mesh_num_textures && (mesh->flags & MESH_HAS_COLOR)) {
    2803           0 :                 glEnable(GL_COLOR_MATERIAL);
    2804             : #if !defined (GPAC_USE_GLES1X)
    2805           0 :                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
    2806             : #endif
    2807           0 :                 glEnableClientState(GL_COLOR_ARRAY);
    2808             :                 has_col = 1;
    2809             : 
    2810             : #if defined (GPAC_USE_GLES1X)
    2811             : 
    2812             :                 if (mesh->flags & MESH_HAS_ALPHA) {
    2813             :                         glEnable(GL_BLEND);
    2814             :                         tr_state->mesh_is_transparent = 1;
    2815             :                 }
    2816             : #ifdef MESH_USE_SFCOLOR
    2817             :                 /*glES only accepts full RGBA colors*/
    2818             :                 glColorPointer(4, GL_FIXED, sizeof(GF_Vertex), ((char *)base_address + MESH_COLOR_OFFSET));
    2819             : #else
    2820             :                 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(GF_Vertex), ((char *)base_address + MESH_COLOR_OFFSET));
    2821             : #endif  /*MESH_USE_SFCOLOR*/
    2822             : 
    2823             : #elif defined (GPAC_FIXED_POINT)
    2824             : 
    2825             : 
    2826             : #ifdef MESH_USE_SFCOLOR
    2827             :                 /*this is a real pain: we cannot "scale" colors through openGL, and our components are 16.16 (32 bytes) ranging
    2828             :                 from [0 to 65536] mapping to [0, 1.0], but openGL assumes for s32 a range from [-2^31 2^31] mapping to [0, 1.0]
    2829             :                 we must thus rebuild a dedicated array...*/
    2830             :                 if (mesh->flags & MESH_HAS_ALPHA) {
    2831             :                         u32 i;
    2832             :                         color_array = gf_malloc(sizeof(Float)*4*mesh->v_count);
    2833             :                         for (i=0; i<mesh->v_count; i++) {
    2834             :                                 color_array[4*i] = FIX2FLT(mesh->vertices[i].color.red);
    2835             :                                 color_array[4*i+1] = FIX2FLT(mesh->vertices[i].color.green);
    2836             :                                 color_array[4*i+2] = FIX2FLT(mesh->vertices[i].color.blue);
    2837             :                                 color_array[4*i+3] = FIX2FLT(mesh->vertices[i].color.alpha);
    2838             :                         }
    2839             :                         glEnable(GL_BLEND);
    2840             :                         glColorPointer(4, GL_FLOAT, 4*sizeof(Float), color_array);
    2841             :                         tr_state->mesh_is_transparent = 1;
    2842             :                 } else {
    2843             :                         color_array = gf_malloc(sizeof(Float)*3*mesh->v_count);
    2844             :                         for (i=0; i<mesh->v_count; i++) {
    2845             :                                 color_array[3*i] = FIX2FLT(mesh->vertices[i].color.red);
    2846             :                                 color_array[3*i+1] = FIX2FLT(mesh->vertices[i].color.green);
    2847             :                                 color_array[3*i+2] = FIX2FLT(mesh->vertices[i].color.blue);
    2848             :                         }
    2849             :                         glColorPointer(3, GL_FLOAT, 3*sizeof(Float), color_array);
    2850             :                 }
    2851             : #else
    2852             :                 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(GF_Vertex), ((char *)base_address + MESH_COLOR_OFFSET));
    2853             : #endif /*MESH_USE_SFCOLOR*/
    2854             : 
    2855             : #else
    2856             : 
    2857             : #ifdef MESH_USE_SFCOLOR
    2858             :                 if (mesh->flags & MESH_HAS_ALPHA) {
    2859             :                         glEnable(GL_BLEND);
    2860             :                         glColorPointer(4, GL_FLOAT, sizeof(GF_Vertex), ((char *)base_address + MESH_COLOR_OFFSET));
    2861             :                         tr_state->mesh_is_transparent = 1;
    2862             :                 } else {
    2863             :                         glColorPointer(3, GL_FLOAT, sizeof(GF_Vertex), ((char *)base_address + MESH_COLOR_OFFSET));
    2864             :                 }
    2865             : #else
    2866           0 :                 if (mesh->flags & MESH_HAS_ALPHA) {
    2867           0 :                         glEnable(GL_BLEND);
    2868           0 :                         tr_state->mesh_is_transparent = 1;
    2869           0 :                         glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(GF_Vertex), ((char *)base_address + MESH_COLOR_OFFSET));
    2870             :                 } else {
    2871           0 :                         glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(GF_Vertex), ((char *)base_address + MESH_COLOR_OFFSET));
    2872             :                 }
    2873             : #endif /*MESH_USE_SFCOLOR*/
    2874             : 
    2875             : #endif
    2876             :         }
    2877             : 
    2878         164 :         if (tr_state->mesh_num_textures && (mesh->mesh_type==MESH_TRIANGLES) && !(mesh->flags & MESH_NO_TEXTURE)) {
    2879             :                 has_tx = 1;
    2880             : 
    2881           2 :                 glMatrixMode(GL_TEXTURE);
    2882           2 :                 if (visual->has_tx_matrix) {
    2883           2 :                         visual_3d_matrix_load(visual, visual->tx_matrix.m);
    2884             :                 } else {
    2885           0 :                         glLoadIdentity();
    2886             :                 }
    2887           2 :                 glMatrixMode(GL_MODELVIEW);
    2888             : 
    2889             : 
    2890             : #if defined(GPAC_USE_GLES1X)
    2891             :                 glTexCoordPointer(2, GL_FIXED, sizeof(GF_Vertex), ((char *)base_address + MESH_TEX_OFFSET));
    2892             :                 glEnableClientState(GL_TEXTURE_COORD_ARRAY );
    2893             : #elif defined(GPAC_FIXED_POINT)
    2894             :                 glMatrixMode(GL_TEXTURE);
    2895             :                 glPushMatrix();
    2896             :                 glScalef(fix_scale, fix_scale, fix_scale);
    2897             :                 glMatrixMode(GL_MODELVIEW);
    2898             :                 glTexCoordPointer(2, GL_INT, sizeof(GF_Vertex), ((char *)base_address + MESH_TEX_OFFSET));
    2899             :                 glEnableClientState(GL_TEXTURE_COORD_ARRAY );
    2900             : #else
    2901             : 
    2902             : #ifndef GPAC_USE_TINYGL
    2903           2 :                 if (tr_state->mesh_num_textures>1) {
    2904             :                         u32 i;
    2905           0 :                         for (i=0; i<tr_state->mesh_num_textures; i++) {
    2906           0 :                                 glClientActiveTexture(GL_TEXTURE0 + i);
    2907           0 :                                 glTexCoordPointer(2, GL_FLOAT, sizeof(GF_Vertex), ((char *)base_address + MESH_TEX_OFFSET));
    2908           0 :                                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    2909             :                         }
    2910             :                 } else
    2911             : #endif //GPAC_USE_TINYGL
    2912             :                 {
    2913           2 :                         glTexCoordPointer(2, GL_FLOAT, sizeof(GF_Vertex), ((char *)base_address + MESH_TEX_OFFSET));
    2914           2 :                         glEnableClientState(GL_TEXTURE_COORD_ARRAY );
    2915             :                 }
    2916             : #endif
    2917             :         }
    2918             : 
    2919         164 :         if (mesh->mesh_type != MESH_TRIANGLES) {
    2920             : #ifdef GPAC_USE_GLES1X
    2921             :                 glNormal3x(0, 0, FIX_ONE);
    2922             : #else
    2923           0 :                 glNormal3f(0, 0, 1.0f);
    2924             : #endif
    2925           0 :                 glDisable(GL_CULL_FACE);
    2926           0 :                 glDisable(GL_LIGHTING);
    2927           0 :                 if (mesh->mesh_type==MESH_LINESET) glDisable(GL_LINE_SMOOTH);
    2928           0 :                 else glDisable(GL_POINT_SMOOTH);
    2929             : 
    2930             : #if !defined(GPAC_USE_TINYGL) && !defined(GL_ES_CL_PROFILE)
    2931           0 :                 glLineWidth(1.0f);
    2932             : #endif
    2933             : 
    2934             :         } else {
    2935             :                 u32 normal_type = GL_FLOAT;
    2936             :                 has_norm = 1;
    2937         164 :                 glEnableClientState(GL_NORMAL_ARRAY );
    2938             : #ifdef MESH_USE_FIXED_NORMAL
    2939             : 
    2940             : #if defined(GPAC_USE_GLES1X)
    2941             :                 normal_type = GL_FIXED;
    2942             : #elif defined(GPAC_FIXED_POINT)
    2943             :                 normal_type = GL_INT;
    2944             : #else
    2945             :                 normal_type = GL_FLOAT;
    2946             : #endif
    2947             : 
    2948             : #else /*MESH_USE_FIXED_NORMAL*/
    2949             :                 /*normals are stored on signed bytes*/
    2950             :                 normal_type = GL_BYTE;
    2951             : #endif
    2952         164 :                 glNormalPointer(normal_type, sizeof(GF_Vertex), ((char *)base_address + MESH_NORMAL_OFFSET));
    2953             : 
    2954         164 :                 if (mesh->mesh_type==MESH_TRIANGLES) {
    2955         164 :                         if (compositor->bcull
    2956         164 :                                 && (!tr_state->mesh_is_transparent || (compositor->bcull ==GF_BACK_CULL_ALPHA) )
    2957         164 :                                 && (mesh->flags & MESH_IS_SOLID)) {
    2958           0 :                                 glEnable(GL_CULL_FACE);
    2959           0 :                                 glFrontFace((mesh->flags & MESH_IS_CW) ? GL_CW : GL_CCW);
    2960             :                         } else {
    2961         164 :                                 glDisable(GL_CULL_FACE);
    2962             :                         }
    2963             :                 }
    2964             :         }
    2965             : 
    2966             :         GL_CHECK_ERR()
    2967         164 :         visual_3d_do_draw_mesh(tr_state, mesh);
    2968             :         GL_CHECK_ERR()
    2969             : 
    2970         164 :         glDisableClientState(GL_VERTEX_ARRAY);
    2971         164 :         if (has_col) glDisableClientState(GL_COLOR_ARRAY);
    2972         164 :         glDisable(GL_COLOR_MATERIAL);
    2973             : 
    2974         164 :         if (has_tx) glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    2975         164 :         if (has_norm) glDisableClientState(GL_NORMAL_ARRAY);
    2976             : 
    2977         164 :         if (mesh->vbo)
    2978         152 :                 glBindBuffer(GL_ARRAY_BUFFER, 0);
    2979             : 
    2980             : #if defined(GPAC_FIXED_POINT) && !defined(GPAC_USE_GLES1X)
    2981             :         if (color_array) gf_free(color_array);
    2982             :         if (tr_state->mesh_num_textures && (mesh->mesh_type==MESH_TRIANGLES) && !(mesh->flags & MESH_NO_TEXTURE)) {
    2983             :                 glMatrixMode(GL_TEXTURE);
    2984             :                 glPopMatrix();
    2985             :                 glMatrixMode(GL_MODELVIEW);
    2986             :         }
    2987             :         glPopMatrix();
    2988             : #endif
    2989             : 
    2990             : 
    2991         164 :         if (visual->has_clipper_2d) {
    2992           0 :                 glDisable(GL_SCISSOR_TEST);
    2993             :         }
    2994         164 :         visual_3d_reset_lights(visual);
    2995             : 
    2996         164 :         glDisable(GL_COLOR_MATERIAL);
    2997             : 
    2998             :         //reset all our states
    2999             :         visual_3d_reset_clippers(visual);
    3000         164 :         visual->has_material_2d = GF_FALSE;
    3001         164 :         visual->has_material = 0;
    3002         164 :         visual->state_color_on = 0;
    3003         164 :         if (tr_state->mesh_is_transparent) glDisable(GL_BLEND);
    3004         164 :         tr_state->mesh_is_transparent = 0;
    3005             : 
    3006             :         GL_CHECK_ERR()
    3007             : #endif
    3008             : }
    3009             : 
    3010           0 : static void visual_3d_set_debug_color(u32 col)
    3011             : {
    3012             : #ifndef GPAC_USE_GLES2
    3013             : 
    3014             : #ifdef GPAC_USE_GLES1X
    3015             :         glColor4x( (col ? GF_COL_R(col) : 255) , (col ? GF_COL_G(col) : 0) , (col ? GF_COL_B(col) : 255), 255);
    3016             : #else
    3017        1059 :         glColor4f(col ? GF_COL_R(col)/255.0f : 1, col ? GF_COL_G(col)/255.0f : 0, col ? GF_COL_B(col)/255.0f : 1, 1);
    3018             : #endif
    3019             : 
    3020             : 
    3021             : #endif //GPAC_USE_GLES2
    3022           0 : }
    3023             : 
    3024             : 
    3025             : /*note we don't perform any culling for normal drawing...*/
    3026         152 : static void visual_3d_draw_normals(GF_TraverseState *tr_state, GF_Mesh *mesh)
    3027             : {
    3028             : #if !defined( GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES2)
    3029             : 
    3030             :         GF_Vec pt, end;
    3031             :         u32 i, j;
    3032         152 :         Fixed scale = mesh->bounds.radius / 4;
    3033             : 
    3034             : #ifdef GPAC_USE_GLES1X
    3035             :         GF_Vec va[2];
    3036             :         u16 indices[2];
    3037             :         glEnableClientState(GL_VERTEX_ARRAY);
    3038             : #endif
    3039             : 
    3040             :         visual_3d_set_debug_color(0);
    3041             : 
    3042             : #if !defined(GPAC_DISABLE_3D) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
    3043             :         //in shader mode force pushing projection and modelview using fixed pipeline API
    3044         152 :         if (!tr_state->visual->compositor->shader_mode_disabled) {
    3045         152 :                 tr_state->visual->needs_projection_matrix_reload=GF_TRUE;
    3046         152 :                 visual_3d_update_matrices(tr_state);
    3047             :         }
    3048             : #endif
    3049             : 
    3050         152 :         if (tr_state->visual->compositor->norms==GF_NORMALS_VERTEX) {
    3051           0 :                 IDX_TYPE *idx = mesh->indices;
    3052           0 :                 for (i=0; i<mesh->i_count; i+=3) {
    3053           0 :                         for (j=0; j<3; j++) {
    3054           0 :                                 pt = mesh->vertices[idx[j]].pos;
    3055           0 :                                 MESH_GET_NORMAL(end, mesh->vertices[idx[j]]);
    3056           0 :                                 end = gf_vec_scale(end, scale);
    3057           0 :                                 gf_vec_add(end, pt, end);
    3058             : #ifdef GPAC_USE_GLES1X
    3059             :                                 va[0] = pt;
    3060             :                                 va[1] = end;
    3061             :                                 indices[0] = 0;
    3062             :                                 indices[1] = 1;
    3063             :                                 glVertexPointer(3, GL_FIXED, 0, va);
    3064             :                                 glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, indices);
    3065             : #else
    3066           0 :                                 glBegin(GL_LINES);
    3067           0 :                                 glVertex3f(FIX2FLT(pt.x), FIX2FLT(pt.y), FIX2FLT(pt.z));
    3068           0 :                                 glVertex3f(FIX2FLT(end.x), FIX2FLT(end.y), FIX2FLT(end.z));
    3069           0 :                                 glEnd();
    3070             : #endif
    3071             :                         }
    3072           0 :                         idx+=3;
    3073             :                 }
    3074             :         } else {
    3075         152 :                 IDX_TYPE *idx = mesh->indices;
    3076      190456 :                 for (i=0; i<mesh->i_count; i+=3) {
    3077      190304 :                         gf_vec_add(pt, mesh->vertices[idx[0]].pos, mesh->vertices[idx[1]].pos);
    3078      190304 :                         gf_vec_add(pt, pt, mesh->vertices[idx[2]].pos);
    3079      190304 :                         pt = gf_vec_scale(pt, FIX_ONE/3);
    3080      190304 :                         MESH_GET_NORMAL(end, mesh->vertices[idx[0]]);
    3081      190304 :                         end = gf_vec_scale(end, scale);
    3082      190304 :                         gf_vec_add(end, pt, end);
    3083             : 
    3084             : #ifdef GPAC_USE_GLES1X
    3085             :                         va[0] = pt;
    3086             :                         va[1] = end;
    3087             :                         indices[0] = 0;
    3088             :                         indices[1] = 1;
    3089             :                         glVertexPointer(3, GL_FIXED, 0, va);
    3090             :                         glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, indices);
    3091             : #else
    3092      190304 :                         glBegin(GL_LINES);
    3093      190304 :                         glVertex3f(FIX2FLT(pt.x), FIX2FLT(pt.y), FIX2FLT(pt.z));
    3094      190304 :                         glVertex3f(FIX2FLT(end.x), FIX2FLT(end.y), FIX2FLT(end.z));
    3095      190304 :                         glEnd();
    3096             : #endif
    3097      190304 :                         idx += 3;
    3098             :                 }
    3099             :         }
    3100             : #ifdef GPAC_USE_GLES1X
    3101             :         glDisableClientState(GL_VERTEX_ARRAY);
    3102             : #endif
    3103             : 
    3104             : #endif  /*GPAC_USE_TINYGL*/
    3105         152 : }
    3106             : 
    3107             : 
    3108       34048 : void visual_3d_draw_aabb_nodeBounds(GF_TraverseState *tr_state, AABBNode *node)
    3109             : {
    3110       67944 :         if (node->pos) {
    3111       33896 :                 visual_3d_draw_aabb_nodeBounds(tr_state, node->pos);
    3112       33896 :                 visual_3d_draw_aabb_nodeBounds(tr_state, node->neg);
    3113             :         } else {
    3114             :                 GF_Matrix mx;
    3115             :                 SFVec3f c, s;
    3116       34048 :                 gf_vec_diff(s, node->max, node->min);
    3117       34048 :                 c = gf_vec_scale(s, FIX_ONE/2);
    3118       34048 :                 gf_vec_add(c, node->min, c);
    3119             : 
    3120       34048 :                 gf_mx_copy(mx, tr_state->model_matrix);
    3121       34048 :                 gf_mx_add_translation(&tr_state->model_matrix, c.x, c.y, c.z);
    3122       34048 :                 gf_mx_add_scale(&tr_state->model_matrix, s.x, s.y, s.z);
    3123             : 
    3124       34048 :                 visual_3d_draw_mesh(tr_state, NULL);
    3125             : 
    3126             :                 gf_mx_copy(tr_state->model_matrix, mx);
    3127             :         }
    3128       34048 : }
    3129             : 
    3130         755 : void visual_3d_draw_bbox(GF_TraverseState *tr_state, GF_BBox *box, Bool is_debug)
    3131             : {
    3132             :         GF_Matrix mx;
    3133             :         SFVec3f c, s;
    3134             : 
    3135         755 :         if (! is_debug) {
    3136           0 :                 visual_3d_set_debug_color(tr_state->visual->compositor->hlline);
    3137             :         }
    3138             : 
    3139         755 :         gf_vec_diff(s, box->max_edge, box->min_edge);
    3140         755 :         c.x = box->min_edge.x + s.x/2;
    3141         755 :         c.y = box->min_edge.y + s.y/2;
    3142         755 :         c.z = box->min_edge.z + s.z/2;
    3143             : 
    3144         755 :         gf_mx_copy(mx, tr_state->model_matrix);
    3145         755 :         gf_mx_add_translation(&tr_state->model_matrix, c.x, c.y, c.z);
    3146         755 :         gf_mx_add_scale(&tr_state->model_matrix, s.x, s.y, s.z);
    3147             : 
    3148         755 :         visual_3d_draw_mesh(tr_state, NULL);
    3149             :         gf_mx_copy(tr_state->model_matrix, mx);
    3150         755 : }
    3151             : 
    3152         907 : static void visual_3d_draw_bounds(GF_TraverseState *tr_state, GF_Mesh *mesh)
    3153             : {
    3154             :         visual_3d_set_debug_color(0);
    3155             : 
    3156         907 :         if (mesh->aabb_root && (tr_state->visual->compositor->bvol==GF_BOUNDS_AABB)) {
    3157         152 :                 visual_3d_draw_aabb_nodeBounds(tr_state, mesh->aabb_root);
    3158             :         } else {
    3159         755 :                 visual_3d_draw_bbox(tr_state, &mesh->bounds, GF_TRUE);
    3160             :         }
    3161         907 : }
    3162             : 
    3163       28804 : void visual_3d_mesh_paint(GF_TraverseState *tr_state, GF_Mesh *mesh)
    3164             : {
    3165             : #if !defined(GPAC_USE_GLES2)
    3166             :         Bool mesh_drawn = 0;
    3167             : #endif
    3168             : 
    3169             :         GL_CHECK_ERR()
    3170             : 
    3171       28804 :         gf_rmt_begin_gl(visual_3d_mesh_paint);
    3172       28804 :         glGetError();
    3173             : 
    3174       28804 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[V3D] Drawing mesh %p\n", mesh));
    3175       28804 :         if (tr_state->visual->compositor->wire != GF_WIREFRAME_ONLY) {
    3176       28804 :                 visual_3d_draw_mesh(tr_state, mesh);
    3177             : #if !defined(GPAC_USE_GLES2)
    3178             :                 mesh_drawn = 1;
    3179             : #endif
    3180             :         }
    3181             : 
    3182             : #if !defined(GPAC_USE_GLES2)
    3183       28804 :         if (tr_state->visual->compositor->norms) {
    3184         152 :                 if (!mesh_drawn) {
    3185           0 :                         visual_3d_update_matrices(tr_state);
    3186             :                         mesh_drawn=1;
    3187             :                 }
    3188         152 :                 visual_3d_draw_normals(tr_state, mesh);
    3189             :         }
    3190             : 
    3191       28804 :         if ((mesh->mesh_type==MESH_TRIANGLES) && (tr_state->visual->compositor->wire != GF_WIREFRAME_NONE)) {
    3192           0 :                 glDisable(GL_LIGHTING);
    3193             :                 visual_3d_set_debug_color(0xFFFFFFFF);
    3194             : 
    3195           0 :                 if (!mesh_drawn)
    3196           0 :                         visual_3d_update_matrices(tr_state);
    3197             : 
    3198             : 
    3199           0 :                 glEnableClientState(GL_VERTEX_ARRAY);
    3200             : #ifdef GPAC_USE_GLES1X
    3201             :                 glVertexPointer(3, GL_FIXED, sizeof(GF_Vertex),  &mesh->vertices[0].pos);
    3202             :                 glDrawElements(GL_LINES, mesh->i_count, GL_UNSIGNED_SHORT, mesh->indices);
    3203             : #else
    3204           0 :                 glVertexPointer(3, GL_FLOAT, sizeof(GF_Vertex),  &mesh->vertices[0].pos);
    3205           0 :                 glDrawElements(GL_LINES, mesh->i_count, GL_UNSIGNED_INT, mesh->indices);
    3206             : #endif
    3207           0 :                 glDisableClientState(GL_VERTEX_ARRAY);
    3208             :         }
    3209             : 
    3210             : #endif
    3211             : 
    3212       28804 :         if (tr_state->visual->compositor->bvol)
    3213         907 :                 visual_3d_draw_bounds(tr_state, mesh);
    3214             : 
    3215       28804 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[V3D] Done drawing mesh %p\n", mesh));
    3216             : 
    3217       28804 :         gf_rmt_end_gl();
    3218       28804 :         glGetError();
    3219       28804 : }
    3220             : 
    3221             : #if !defined(GPAC_USE_GLES1X) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES2)
    3222             : 
    3223             : 
    3224             : static GLubyte hatch_horiz[] = {
    3225             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
    3226             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
    3227             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
    3228             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
    3229             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
    3230             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
    3231             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
    3232             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
    3233             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
    3234             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
    3235             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
    3236             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
    3237             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
    3238             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
    3239             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
    3240             :         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
    3241             : };
    3242             : 
    3243             : static GLubyte hatch_vert[] = {
    3244             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
    3245             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
    3246             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
    3247             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
    3248             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
    3249             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
    3250             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
    3251             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
    3252             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
    3253             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
    3254             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
    3255             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
    3256             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
    3257             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
    3258             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
    3259             :         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
    3260             : };
    3261             : 
    3262             : static GLubyte hatch_up[] = {
    3263             :         0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
    3264             :         0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03,
    3265             :         0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
    3266             :         0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03,
    3267             :         0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
    3268             :         0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03,
    3269             :         0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
    3270             :         0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03,
    3271             :         0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
    3272             :         0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03,
    3273             :         0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
    3274             :         0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03,
    3275             :         0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
    3276             :         0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03,
    3277             :         0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
    3278             :         0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03
    3279             : };
    3280             : 
    3281             : static GLubyte hatch_down[] = {
    3282             :         0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
    3283             :         0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0,
    3284             :         0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
    3285             :         0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0,
    3286             :         0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
    3287             :         0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0,
    3288             :         0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
    3289             :         0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0,
    3290             :         0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
    3291             :         0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0,
    3292             :         0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
    3293             :         0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0,
    3294             :         0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
    3295             :         0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0,
    3296             :         0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
    3297             :         0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0
    3298             : };
    3299             : 
    3300             : static GLubyte hatch_cross[] = {
    3301             :         0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
    3302             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    3303             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    3304             :         0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
    3305             :         0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
    3306             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    3307             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    3308             :         0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
    3309             :         0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
    3310             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    3311             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    3312             :         0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
    3313             :         0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
    3314             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    3315             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    3316             :         0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c
    3317             : };
    3318             : 
    3319           2 : void visual_3d_mesh_hatch(GF_TraverseState *tr_state, GF_Mesh *mesh, u32 hatchStyle, SFColor hatchColor)
    3320             : {
    3321           2 :         if (mesh->mesh_type != MESH_TRIANGLES) return;
    3322             : 
    3323           2 :         glEnableClientState(GL_VERTEX_ARRAY);
    3324           2 :         glVertexPointer(3, GL_FLOAT, sizeof(GF_Vertex),  &mesh->vertices[0].pos);
    3325           2 :         if (mesh->flags & MESH_IS_2D) {
    3326           0 :                 glDisableClientState(GL_NORMAL_ARRAY);
    3327           0 :                 glNormal3f(0, 0, 1.0f);
    3328           0 :                 glDisable(GL_CULL_FACE);
    3329             :         } else {
    3330           2 :                 glEnableClientState(GL_NORMAL_ARRAY );
    3331           2 :                 glNormalPointer(GL_FLOAT, sizeof(GF_Vertex), &mesh->vertices[0].normal);
    3332             : 
    3333             :                 /*if mesh is transparent DON'T CULL*/
    3334           2 :                 if (!tr_state->mesh_is_transparent && (mesh->flags & MESH_IS_SOLID)) {
    3335           2 :                         glEnable(GL_CULL_FACE);
    3336           2 :                         glFrontFace((mesh->flags & MESH_IS_CW) ? GL_CW : GL_CCW);
    3337             :                 } else {
    3338           0 :                         glDisable(GL_CULL_FACE);
    3339             :                 }
    3340             :         }
    3341             : 
    3342           2 :         glEnable(GL_POLYGON_STIPPLE);
    3343           2 :         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    3344             :         /*can't access ISO International Register of Graphical Items www site :)*/
    3345           2 :         switch (hatchStyle) {
    3346           2 :         case 5:
    3347           2 :                 glPolygonStipple(hatch_cross);
    3348           2 :                 break;
    3349           0 :         case 4:
    3350           0 :                 glPolygonStipple(hatch_up);
    3351           0 :                 break;
    3352           0 :         case 3:
    3353           0 :                 glPolygonStipple(hatch_down);
    3354           0 :                 break;
    3355           0 :         case 2:
    3356           0 :                 glPolygonStipple(hatch_vert);
    3357           0 :                 break;
    3358           0 :         case 1:
    3359           0 :                 glPolygonStipple(hatch_horiz);
    3360           0 :                 break;
    3361           0 :         default:
    3362           0 :                 glDisable(GL_POLYGON_STIPPLE);
    3363           0 :                 break;
    3364             :         }
    3365           2 :         glColor3f(FIX2FLT(hatchColor.red), FIX2FLT(hatchColor.green), FIX2FLT(hatchColor.blue));
    3366           2 :         glDrawElements(GL_TRIANGLES, mesh->i_count, GL_UNSIGNED_INT, mesh->indices);
    3367             : 
    3368           2 :         glDisable(GL_POLYGON_STIPPLE);
    3369             : }
    3370             : #endif
    3371             : 
    3372             : /*only used for ILS/ILS2D or IFS2D outline*/
    3373           0 : void visual_3d_mesh_strike(GF_TraverseState *tr_state, GF_Mesh *mesh, Fixed width, Fixed line_scale, u32 dash_style)
    3374             : {
    3375             : #if !defined(GPAC_USE_GLES1X) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES2)
    3376             :         u16 style;
    3377             : #endif
    3378             : 
    3379           0 :         if (mesh->mesh_type != MESH_LINESET) return;
    3380           0 :         if (line_scale) width = gf_mulfix(width, line_scale);
    3381           0 :         width/=2;
    3382             : #if !defined(GPAC_USE_TINYGL) && !defined(GL_ES_CL_PROFILE)
    3383           0 :         glLineWidth( FIX2FLT(width));
    3384             : #endif
    3385             : 
    3386             : #if !defined(GPAC_USE_GLES1X) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES2)
    3387             : 
    3388           0 :         switch (dash_style) {
    3389             :         case GF_DASH_STYLE_DASH:
    3390             :                 style = 0x1F1F;
    3391             :                 break;
    3392             :         case GF_DASH_STYLE_DOT:
    3393             :                 style = 0x3333;
    3394             :                 break;
    3395             :         case GF_DASH_STYLE_DASH_DOT:
    3396             :                 style = 0x6767;
    3397             :                 break;
    3398             :         case GF_DASH_STYLE_DASH_DASH_DOT:
    3399             :                 style = 0x33CF;
    3400             :                 break;
    3401             :         case GF_DASH_STYLE_DASH_DOT_DOT:
    3402             :                 style = 0x330F;
    3403             :                 break;
    3404             :         default:
    3405             :                 style = 0;
    3406             :                 break;
    3407             :         }
    3408             :         if (style) {
    3409           0 :                 u32 factor = FIX2INT(width);
    3410           0 :                 if (!factor) factor = 1;
    3411           0 :                 glEnable(GL_LINE_STIPPLE);
    3412           0 :                 glLineStipple(factor, style);
    3413           0 :                 visual_3d_mesh_paint(tr_state, mesh);
    3414           0 :                 glDisable (GL_LINE_STIPPLE);
    3415             :         } else
    3416             : #endif
    3417           0 :                 visual_3d_mesh_paint(tr_state, mesh);
    3418             : }
    3419             : 
    3420             : 
    3421        8400 : void visual_3d_clear(GF_VisualManager *visual, SFColor color, Fixed alpha)
    3422             : {
    3423             : #ifdef GPAC_USE_GLES1X
    3424             :         glClearColorx(color.red, color.green, color.blue, alpha);
    3425             : #else
    3426        8400 :         glClearColor(FIX2FLT(color.red), FIX2FLT(color.green), FIX2FLT(color.blue), FIX2FLT(alpha));
    3427             : #endif
    3428        8400 :         glClear(GL_COLOR_BUFFER_BIT);
    3429        8400 : }
    3430             : 
    3431             : 
    3432           0 : void visual_3d_fill_rect(GF_VisualManager *visual, GF_Rect rc, SFColorRGBA color)
    3433             : {
    3434             :         //TODOk - code this for GLES2 ?
    3435             : #ifdef GPAC_USE_GLES2
    3436             : #else
    3437             : 
    3438           0 :         glDisable(GL_BLEND | GL_LIGHTING | GL_TEXTURE_2D);
    3439             : 
    3440             : #if defined(GPAC_USE_GLES1X)
    3441             :         glNormal3x(0, 0, FIX_ONE);
    3442             :         if (color.alpha!=FIX_ONE) glEnable(GL_BLEND);
    3443             :         glColor4x(color.red, color.green, color.blue, color.alpha);
    3444             :         {
    3445             :                 Fixed v[8];
    3446             :                 u16 indices[3];
    3447             :                 indices[0] = 0;
    3448             :                 indices[1] = 1;
    3449             :                 indices[2] = 2;
    3450             : 
    3451             :                 v[0] = rc.x;
    3452             :                 v[1] = rc.y;
    3453             :                 v[2] = rc.x+rc.width;
    3454             :                 v[3] = rc.y-rc.height;
    3455             :                 v[4] = rc.x+rc.width;
    3456             :                 v[5] = rc.y;
    3457             :                 glEnableClientState(GL_VERTEX_ARRAY);
    3458             :                 glVertexPointer(2, GL_FIXED, 0, v);
    3459             :                 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, indices);
    3460             : 
    3461             :                 v[4] = rc.x;
    3462             :                 v[5] = rc.y-rc.height;
    3463             :                 glVertexPointer(2, GL_FIXED, 0, v);
    3464             :                 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, indices);
    3465             : 
    3466             :                 glDisableClientState(GL_VERTEX_ARRAY);
    3467             :         }
    3468             : #else
    3469           0 :         glNormal3f(0, 0, 1);
    3470           0 :         if (color.alpha!=FIX_ONE) {
    3471           0 :                 glEnable(GL_BLEND);
    3472           0 :                 glColor4f(FIX2FLT(color.red), FIX2FLT(color.green), FIX2FLT(color.blue), FIX2FLT(color.alpha));
    3473             :         } else {
    3474           0 :                 glColor3f(FIX2FLT(color.red), FIX2FLT(color.green), FIX2FLT(color.blue));
    3475             :         }
    3476           0 :         glBegin(GL_QUADS);
    3477           0 :         glVertex3f(FIX2FLT(rc.x), FIX2FLT(rc.y), 0);
    3478           0 :         glVertex3f(FIX2FLT(rc.x), FIX2FLT(rc.y-rc.height), 0);
    3479           0 :         glVertex3f(FIX2FLT(rc.x+rc.width), FIX2FLT(rc.y-rc.height), 0);
    3480           0 :         glVertex3f(FIX2FLT(rc.x+rc.width), FIX2FLT(rc.y), 0);
    3481           0 :         glEnd();
    3482             : 
    3483           0 :         glDisable(GL_COLOR_MATERIAL | GL_COLOR_MATERIAL_FACE);
    3484             : #endif
    3485             : 
    3486           0 :         glDisable(GL_BLEND);
    3487             : #endif
    3488           0 : }
    3489             : 
    3490             : //note that we always use glReadPixel even if the actual rendering target is a texture
    3491             : //this is the recommended way by khronos any way
    3492        6773 : GF_Err compositor_3d_get_screen_buffer(GF_Compositor *compositor, GF_VideoSurface *fb, u32 depth_dump_mode)
    3493             : {
    3494             :         u32 i;
    3495             : 
    3496        6773 :         fb->width = compositor->display_width;
    3497        6773 :         fb->height = compositor->display_height;
    3498             : 
    3499             :         /*depthmap-only dump*/
    3500        6773 :         if (depth_dump_mode==1) {
    3501             :                 //depth reading not supported on gles <= 1.1
    3502             : #ifdef GPAC_USE_GLES1X
    3503             :                 return GF_NOT_SUPPORTED;
    3504             : #else
    3505             :                 Float *depthp;
    3506             :                 Float zFar, zNear;
    3507             : 
    3508           0 :                 fb->pitch_x = 0;
    3509           0 :                 fb->pitch_y = compositor->vp_width;
    3510             : 
    3511           0 :                 if (compositor->screen_buffer_alloc_size < fb->pitch_y * fb->height) {
    3512           0 :                         compositor->screen_buffer_alloc_size = fb->pitch_y * fb->height;
    3513           0 :                         compositor->screen_buffer = gf_realloc(compositor->screen_buffer, compositor->screen_buffer_alloc_size);
    3514             :                 }
    3515             : 
    3516           0 :                 fb->video_buffer = compositor->screen_buffer;
    3517             : 
    3518             :                 //read as float
    3519           0 :                 depthp = (Float*)gf_malloc(sizeof(Float)* fb->pitch_y * fb->height);
    3520           0 :                 fb->pixel_format = GF_PIXEL_GREYSCALE;
    3521             : 
    3522             : #ifndef GPAC_USE_TINYGL
    3523             :                 //glPixelTransferf(GL_DEPTH_SCALE, FIX2FLT(compositor->OGLDepthGain) );
    3524             :                 //glPixelTransferf(GL_DEPTH_BIAS, FIX2FLT(compositor->OGLDepthOffset) );
    3525             : #endif
    3526             : 
    3527           0 :                 glReadPixels(compositor->vp_x, compositor->vp_y, fb->width, fb->height, GL_DEPTH_COMPONENT, GL_FLOAT, depthp);
    3528             : 
    3529             :                 //linearize z buffer, from 0 (zfar) to 1 (znear)
    3530           0 :                 zFar = FIX2FLT(compositor->visual->camera.z_far);
    3531           0 :                 zNear = FIX2FLT(compositor->visual->camera.z_near);
    3532           0 :                 for (i=0; i<fb->height*fb->width; i++) {
    3533           0 :                         Float res = ( (2.0f * zNear) / (zFar + zNear - depthp[i] * (zFar - zNear)) ) ;
    3534           0 :                         fb->video_buffer[i] = (u8) ( 255.0 * (1.0 - res));
    3535             :                 }
    3536             : 
    3537           0 :                 gf_free(depthp);
    3538             : 
    3539             : #endif  /*GPAC_USE_GLES1X*/
    3540             :         }
    3541             : 
    3542             :         /* RGBDS or RGBD dump*/
    3543        6773 :         else if (depth_dump_mode==2 || depth_dump_mode==3) {
    3544             : #ifdef GPAC_USE_GLES1X
    3545             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor]: RGB+Depth format not implemented in OpenGL ES\n"));
    3546             :                 return GF_NOT_SUPPORTED;
    3547             : #else
    3548             :                 char *depth_data=NULL;
    3549             :                 u32 size;
    3550           0 :                 fb->pitch_x = 4;
    3551           0 :                 fb->pitch_y = compositor->vp_width*4; /* 4 bytes for each rgbds pixel */
    3552             : 
    3553             : #ifndef GPAC_USE_TINYGL
    3554           0 :                 size = fb->pitch_y * fb->height;
    3555             : #else
    3556             :                 size = 2 * fb->pitch_y * fb->height;
    3557             : #endif
    3558           0 :                 if (compositor->screen_buffer_alloc_size < size) {
    3559           0 :                         compositor->screen_buffer_alloc_size = size;
    3560           0 :                         compositor->screen_buffer = gf_realloc(compositor->screen_buffer, compositor->screen_buffer_alloc_size);
    3561             :                 }
    3562           0 :                 fb->video_buffer = compositor->screen_buffer;
    3563             : 
    3564             : #ifndef GPAC_USE_TINYGL
    3565             : 
    3566           0 :                 glReadPixels(0, 0, fb->width, fb->height, GL_RGBA, GL_UNSIGNED_BYTE, fb->video_buffer);
    3567             : 
    3568             :                 /*
    3569             :                 glPixelTransferf(GL_DEPTH_SCALE, FIX2FLT(compositor->OGLDepthGain));
    3570             :                 glPixelTransferf(GL_DEPTH_BIAS, FIX2FLT(compositor->OGLDepthOffset));
    3571             :                 */
    3572             : 
    3573           0 :                 depth_data = (char*) gf_malloc(sizeof(char)*fb->width*fb->height);
    3574           0 :                 glReadPixels(0, 0, fb->width, fb->height, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, depth_data);
    3575             : 
    3576           0 :                 if (depth_dump_mode==2) {
    3577           0 :                         fb->pixel_format = GF_PIXEL_RGBDS;
    3578             : 
    3579             :                         /*this corresponds to the RGBDS ordering*/
    3580           0 :                         for (i=0; i<fb->height*fb->width; i++) {
    3581             :                                 u8 ds;
    3582             :                                 /* erase lowest-weighted depth bit */
    3583           0 :                                 u8 depth = depth_data[i] & 0xfe;
    3584             :                                 /*get alpha*/
    3585           0 :                                 ds = (fb->video_buffer[i*4 + 3]);
    3586             :                                 /* if heaviest-weighted alpha bit is set (>128) , turn on shape bit*/
    3587           0 :                                 if (ds & 0x80) depth |= 0x01;
    3588           0 :                                 fb->video_buffer[i*4+3] = depth; /*insert depth onto alpha*/
    3589             :                         }
    3590             :                         /*this corresponds to RGBD ordering*/
    3591           0 :                 } else if (depth_dump_mode==3) {
    3592           0 :                         fb->pixel_format = GF_PIXEL_RGBD;
    3593           0 :                         for (i=0; i<fb->height*fb->width; i++)
    3594           0 :                                 fb->video_buffer[i*4+3] = depth_data[i];
    3595             :                 }
    3596             : #else
    3597             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor]: RGB+Depth format not implemented in TinyGL\n"));
    3598             :                 return GF_NOT_SUPPORTED;
    3599             : #endif
    3600             : 
    3601             : #endif /*GPAC_USE_GLES1X*/
    3602             :         } else { /*if (compositor->user && (compositor->user->init_flags & GF_TERM_WINDOW_TRANSPARENT))*/
    3603             :                 u32 size;
    3604        6773 :                 fb->pitch_x = 3;
    3605        6773 :                 if (!compositor->opfmt && compositor->dyn_filter_mode) {
    3606           0 :                         fb->pitch_x = 4;
    3607        6773 :                 } else if (compositor->opfmt==GF_PIXEL_RGBA) {
    3608           4 :                         fb->pitch_x = 4;
    3609             :                 }
    3610             : 
    3611        6773 :                 fb->pitch_y = fb->pitch_x * compositor->vp_width;
    3612        6773 :                 size = fb->pitch_y * fb->height;
    3613        6773 :                 if (compositor->screen_buffer_alloc_size < size) {
    3614         121 :                         compositor->screen_buffer_alloc_size = size;
    3615         121 :                         compositor->screen_buffer = gf_realloc(compositor->screen_buffer, compositor->screen_buffer_alloc_size);
    3616         121 :                         compositor->line_buffer = gf_realloc(compositor->line_buffer, fb->pitch_y);
    3617             : 
    3618             :                 }
    3619             : 
    3620        6773 :                 fb->video_buffer = compositor->screen_buffer;
    3621             : 
    3622        6773 :                 fb->pixel_format = (fb->pitch_x == 4) ? GF_PIXEL_RGBA : GF_PIXEL_RGB;
    3623             : 
    3624        6773 :                 if (compositor->fbo_id) compositor_3d_enable_fbo(compositor, GF_TRUE);
    3625             : 
    3626        6773 :                 glReadPixels(0, 0, fb->width, fb->height, (fb->pitch_x == 4) ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, fb->video_buffer);
    3627             : 
    3628        6773 :                 if (compositor->fbo_id) compositor_3d_enable_fbo(compositor, GF_FALSE);
    3629             : 
    3630             :                 /*      } else {
    3631             :                                 fb->pitch_x = 3;
    3632             :                                 fb->pitch_y = 3*compositor->vp_width;
    3633             :                                 fb->video_buffer = (char*)gf_malloc(sizeof(char) * fb->pitch_y * fb->height);
    3634             :                                 fb->pixel_format = GF_PIXEL_RGB;
    3635             : 
    3636             :                                 glReadPixels(compositor->vp_x, compositor->vp_y, fb->width, fb->height, GL_RGB, GL_UNSIGNED_BYTE, fb->video_buffer);
    3637             :                 */
    3638             :         }
    3639             : 
    3640             : #ifndef GPAC_USE_TINYGL
    3641             :         /*flip image (openGL always handle image data bottom to top) */
    3642        6773 :         u32 hy = fb->height/2;
    3643      655037 :         for (i=0; i<hy; i++) {
    3644      648264 :                 memcpy(compositor->line_buffer, fb->video_buffer+ i*fb->pitch_y, fb->pitch_y);
    3645      648264 :                 memcpy(fb->video_buffer + i*fb->pitch_y, fb->video_buffer + (fb->height - 1 - i) * fb->pitch_y, fb->pitch_y);
    3646      648264 :                 memcpy(fb->video_buffer + (fb->height - 1 - i) * fb->pitch_y, compositor->line_buffer, fb->pitch_y);
    3647             :         }
    3648             : #endif
    3649        6773 :         return GF_OK;
    3650             : }
    3651             : 
    3652        6773 : GF_Err compositor_3d_release_screen_buffer(GF_Compositor *compositor, GF_VideoSurface *framebuffer)
    3653             : {
    3654        6773 :         framebuffer->video_buffer = 0;
    3655        6773 :         return GF_OK;
    3656             : }
    3657             : 
    3658           0 : GF_Err compositor_3d_get_offscreen_buffer(GF_Compositor *compositor, GF_VideoSurface *fb, u32 view_idx, u32 depth_dump_mode)
    3659             : {
    3660             :         //TODOk - habdle offscreen buffers through frameBuffer objects, no read back j
    3661             : #if !defined(GPAC_USE_GLES1X) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES2)
    3662             :         char *tmp;
    3663             :         u32 hy, i;
    3664             :         /*not implemented yet*/
    3665           0 :         if (depth_dump_mode) return GF_NOT_SUPPORTED;
    3666             : 
    3667           0 :         if (view_idx>=compositor->visual->nb_views) return GF_BAD_PARAM;
    3668           0 :         fb->width = compositor->visual->auto_stereo_width;
    3669           0 :         fb->height = compositor->visual->auto_stereo_height;
    3670           0 :         fb->pixel_format = GF_PIXEL_RGB;
    3671           0 :         fb->pitch_y = 3*fb->width;
    3672           0 :         fb->video_buffer = gf_malloc(sizeof(char)*3*fb->width*fb->height);
    3673           0 :         if (!fb->video_buffer) return GF_OUT_OF_MEM;
    3674             : 
    3675           0 :         glEnable(GL_TEXTURE_2D);
    3676           0 :         glBindTexture(GL_TEXTURE_2D, compositor->visual->gl_textures[view_idx]);
    3677           0 :         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, fb->video_buffer);
    3678           0 :         glDisable(GL_TEXTURE_2D);
    3679             : 
    3680             :         /*flip image (openGL always handle image data bottom to top) */
    3681           0 :         tmp = (char*)gf_malloc(sizeof(char)*fb->pitch_y);
    3682           0 :         hy = fb->height/2;
    3683           0 :         for (i=0; i<hy; i++) {
    3684           0 :                 memcpy(tmp, fb->video_buffer+ i*fb->pitch_y, fb->pitch_y);
    3685           0 :                 memcpy(fb->video_buffer + i*fb->pitch_y, fb->video_buffer + (fb->height - 1 - i) * fb->pitch_y, fb->pitch_y);
    3686           0 :                 memcpy(fb->video_buffer + (fb->height - 1 - i) * fb->pitch_y, tmp, fb->pitch_y);
    3687             :         }
    3688           0 :         gf_free(tmp);
    3689           0 :         return GF_OK;
    3690             : #else
    3691             :         return GF_NOT_SUPPORTED;
    3692             : #endif
    3693             : }
    3694             : 
    3695           0 : void visual_3d_point_sprite(GF_VisualManager *visual, Drawable *stack, GF_TextureHandler *txh, GF_TraverseState *tr_state)
    3696             : {
    3697             :         //todo - allow point sprites for GLES2 ?
    3698             : #if !defined(GPAC_USE_GLES1X) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES2)
    3699             :         u32 w, h;
    3700             :         u32 pixel_format, stride;
    3701             :         u8 *data;
    3702             :         Float r, g, b;
    3703             :         Fixed x, y;
    3704             :         Float inc, scale;
    3705             :         Bool in_strip;
    3706             :         GF_Node *txtrans = NULL;
    3707             : 
    3708           0 :         if ((visual->compositor->depth_gl_type==GF_SC_DEPTH_GL_POINTS) && visual->compositor->gl_caps.point_sprite) {
    3709             :                 Float z;
    3710             :                 static GLfloat none[3] = { 1.0f, 0, 0 };
    3711             : 
    3712           0 :                 data = (u8 *) gf_sc_texture_get_data(txh, &pixel_format);
    3713           0 :                 if (!data) return;
    3714           0 :                 if (pixel_format!=GF_PIXEL_RGBD) return;
    3715           0 :                 stride = txh->stride;
    3716           0 :                 if (txh->pixelformat==GF_PIXEL_YUVD) stride *= 4;
    3717             : 
    3718           0 :                 glPointSize(1.0f * visual->compositor->zoom);
    3719           0 :                 glDepthMask(GL_FALSE);
    3720             : 
    3721           0 :                 glPointParameterfv(GL_DISTANCE_ATTENUATION_EXT, none);
    3722           0 :                 glPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_EXT, 0.0);
    3723           0 :                 glEnable(GL_POINT_SMOOTH);
    3724           0 :                 glDisable(GL_LIGHTING);
    3725             : 
    3726             : //              scale = FIX2FLT(visual->compositor->depth_gl_scale);
    3727             :                 inc = 1;
    3728           0 :                 if (!tr_state->pixel_metrics) inc /= FIX2FLT(tr_state->min_hsize);
    3729             : //              x = 0;
    3730             :                 y = 1;
    3731           0 :                 y = gf_mulfix(y, INT2FIX(txh->height/2));
    3732           0 :                 if (!tr_state->pixel_metrics) y = gf_divfix(y, tr_state->min_hsize);
    3733             : 
    3734           0 :                 glBegin(GL_POINTS);
    3735           0 :                 for (h=0; h<txh->height; h++) {
    3736             :                         x = -1;
    3737           0 :                         x = gf_mulfix(x, INT2FIX(txh->width/2));
    3738           0 :                         if (!tr_state->pixel_metrics) x = gf_divfix(x, tr_state->min_hsize);
    3739           0 :                         for (w=0; w<txh->width; w++) {
    3740           0 :                                 u8 *p = data + h*stride + w*4;
    3741           0 :                                 r = p[0];
    3742           0 :                                 r /= 255;
    3743           0 :                                 g = p[1];
    3744           0 :                                 g /= 255;
    3745           0 :                                 b = p[2];
    3746           0 :                                 b /= 255;
    3747           0 :                                 z = p[3];
    3748           0 :                                 z = z / 255;
    3749             : 
    3750           0 :                                 glColor4f(r, g, b, 1.0);
    3751           0 :                                 glVertex3f(FIX2FLT(x), FIX2FLT(y), FIX2FLT(-z)*60);
    3752           0 :                                 x += FLT2FIX(inc);
    3753             :                         }
    3754           0 :                         y -= FLT2FIX(inc);
    3755             :                 }
    3756           0 :                 glEnd();
    3757             : 
    3758           0 :                 glDepthMask(GL_TRUE);
    3759           0 :                 return;
    3760             :         }
    3761             : 
    3762           0 :         if (visual->compositor->depth_gl_type==GF_SC_DEPTH_GL_STRIPS) {
    3763             :                 u32 first_pass;
    3764           0 :                 Float delta = FIX2FLT(visual->compositor->depth_gl_strips_filter);
    3765           0 :                 if (!delta) first_pass = 2;
    3766             :                 else first_pass = 1;
    3767             : 
    3768           0 :                 data = (u8 *) gf_sc_texture_get_data(txh, &pixel_format);
    3769           0 :                 if (!data) return;
    3770           0 :                 if (pixel_format!=GF_PIXEL_RGBD) return;
    3771           0 :                 stride = txh->stride;
    3772           0 :                 if (txh->pixelformat==GF_PIXEL_YUVD) stride *= 4;
    3773             : 
    3774           0 :                 glDepthMask(GL_FALSE);
    3775           0 :                 glDisable(GL_TEXTURE_2D);
    3776           0 :                 glDisable(GL_LIGHTING);
    3777           0 :                 glDisable(GL_BLEND);
    3778           0 :                 glDisable(GL_CULL_FACE);
    3779           0 :                 glDisable(GL_POINT_SMOOTH);
    3780           0 :                 glDisable(GL_FOG);
    3781             : 
    3782           0 : restart:
    3783           0 :                 scale = FIX2FLT(visual->compositor->depth_gl_scale);
    3784             :                 inc = 1;
    3785           0 :                 if (!tr_state->pixel_metrics) inc /= FIX2FLT(tr_state->min_hsize);
    3786             : //              x = 0;
    3787             :                 y = 1;
    3788           0 :                 y = gf_mulfix(y, INT2FIX(txh->height/2));
    3789           0 :                 if (!tr_state->pixel_metrics) y = gf_divfix(y, tr_state->min_hsize);
    3790             : 
    3791             :                 in_strip = 0;
    3792           0 :                 for (h=0; h<txh->height - 1; h++) {
    3793           0 :                         u8 *src = data + h*stride;
    3794             :                         x = -1;
    3795           0 :                         x = gf_mulfix(x, INT2FIX(txh->width/2));
    3796           0 :                         if (!tr_state->pixel_metrics) x  = gf_divfix(x, tr_state->min_hsize);
    3797             : 
    3798           0 :                         for (w=0; w<txh->width; w++) {
    3799           0 :                                 u8 *p1 = src + w*4;
    3800           0 :                                 u8 *p2 = src + w*4 + stride;
    3801           0 :                                 Float z1 = p1[3];
    3802           0 :                                 Float z2 = p2[3];
    3803           0 :                                 if (first_pass==1) {
    3804           0 :                                         if ((z1>delta) || (z2>delta))
    3805             :                                         {
    3806             : #if 0
    3807             :                                                 if (in_strip) {
    3808             :                                                         glEnd();
    3809             :                                                         in_strip = 0;
    3810             :                                                 }
    3811             : #endif
    3812           0 :                                                 x += FLT2FIX(inc);
    3813           0 :                                                 continue;
    3814             :                                         }
    3815           0 :                                 } else if (first_pass==0) {
    3816           0 :                                         if ((z1<=delta) || (z2<=delta))
    3817             :                                         {
    3818           0 :                                                 if (in_strip) {
    3819           0 :                                                         glEnd();
    3820             :                                                         in_strip = 0;
    3821             :                                                 }
    3822           0 :                                                 x += FLT2FIX(inc);
    3823           0 :                                                 continue;
    3824             :                                         }
    3825             :                                 }
    3826           0 :                                 z1 = z1 / 255;
    3827           0 :                                 z2 = z2 / 255;
    3828             : 
    3829           0 :                                 r = p1[0];
    3830           0 :                                 r /= 255;
    3831           0 :                                 g = p1[1];
    3832           0 :                                 g /= 255;
    3833           0 :                                 b = p1[2];
    3834           0 :                                 b /= 255;
    3835             : 
    3836           0 :                                 if (!in_strip) {
    3837           0 :                                         glBegin(GL_TRIANGLE_STRIP);
    3838             :                                         in_strip = 1;
    3839             :                                 }
    3840             : 
    3841           0 :                                 glColor3f(r, g, b);
    3842           0 :                                 glVertex3f(FIX2FLT(x), FIX2FLT(y), FIX2FLT(z1)*scale);
    3843             : 
    3844           0 :                                 r = p2[0];
    3845           0 :                                 r /= 255;
    3846           0 :                                 g = p2[1];
    3847           0 :                                 g /= 255;
    3848           0 :                                 b = p2[2];
    3849           0 :                                 b /= 255;
    3850             : 
    3851           0 :                                 glColor3f(r, g, b);
    3852           0 :                                 glVertex3f(FIX2FLT(x), FIX2FLT(y)-inc, FIX2FLT(z2)*scale);
    3853             : 
    3854           0 :                                 x += FLT2FIX(inc);
    3855             :                         }
    3856           0 :                         if (in_strip) {
    3857           0 :                                 glEnd();
    3858             :                                 in_strip = 0;
    3859             :                         }
    3860           0 :                         y -= FLT2FIX(inc);
    3861             :                 }
    3862             : 
    3863           0 :                 if (first_pass==1) {
    3864             :                         first_pass = 0;
    3865             :                         goto restart;
    3866             :                 }
    3867             :                 return;
    3868             :         }
    3869             : 
    3870           0 :         glColor3f(1.0, 0.0, 0.0);
    3871             :         /*render using vertex array*/
    3872           0 :         if (!stack->mesh) {
    3873           0 :                 stack->mesh = new_mesh();
    3874           0 :                 stack->mesh->vbo_dynamic = 1;
    3875             :                 inc = 1;
    3876           0 :                 if (!tr_state->pixel_metrics) inc /= FIX2FLT(tr_state->min_hsize);
    3877             : //              x = 0;
    3878             :                 y = 1;
    3879           0 :                 y = gf_mulfix(y, FLT2FIX(txh->height/2));
    3880           0 :                 if (!tr_state->pixel_metrics) y = gf_divfix(y, tr_state->min_hsize);
    3881             : 
    3882           0 :                 if (txh->width>1 && txh->height>1) {
    3883           0 :                         for (h=0; h<txh->height; h++) {
    3884           0 :                                 u32 idx_offset = h ? ((h-1)*txh->width) : 0;
    3885             :                                 x = -1;
    3886           0 :                                 x = gf_mulfix(x, FLT2FIX(txh->width/2));
    3887           0 :                                 if (tr_state->min_hsize && !tr_state->pixel_metrics) x = gf_divfix(x, tr_state->min_hsize);
    3888             : 
    3889           0 :                                 for (w=0; w<txh->width; w++) {
    3890           0 :                                         mesh_set_vertex(stack->mesh, x, y, 0, 0, 0, -FIX_ONE, INT2FIX(w / (txh->width-1)), INT2FIX((txh->height - h  -1) / (txh->height-1)) );
    3891           0 :                                         x += FLT2FIX(inc);
    3892             : 
    3893             :                                         /*set triangle*/
    3894           0 :                                         if (h && w) {
    3895           0 :                                                 u32 first_idx = idx_offset + w - 1;
    3896           0 :                                                 mesh_set_triangle(stack->mesh, first_idx, first_idx+1, txh->width + first_idx +1);
    3897           0 :                                                 mesh_set_triangle(stack->mesh, first_idx, txh->width + first_idx, txh->width + first_idx +1);
    3898             :                                         }
    3899             :                                 }
    3900           0 :                                 y -= FLT2FIX(inc);
    3901             :                         }
    3902             :                         /*force recompute of Z*/
    3903           0 :                         txh->needs_refresh = 1;
    3904             :                 }
    3905             :         }
    3906             : 
    3907             :         /*texture has been updated, recompute Z*/
    3908           0 :         if (txh->needs_refresh) {
    3909           0 :                 Fixed f_scale = FLT2FIX(visual->compositor->depth_gl_scale);
    3910           0 :                 txh->needs_refresh = 0;
    3911             : 
    3912           0 :                 data = (u8 *) gf_sc_texture_get_data(txh, &pixel_format);
    3913           0 :                 if (!data) return;
    3914           0 :                 if (pixel_format!=GF_PIXEL_RGB_DEPTH) return;
    3915           0 :                 data += txh->height*txh->width*3;
    3916             : 
    3917           0 :                 for (h=0; h<txh->height; h++) {
    3918           0 :                         u8 *src = data + h * txh->width;
    3919           0 :                         for (w=0; w<txh->width; w++) {
    3920           0 :                                 u8 d = src[w];
    3921           0 :                                 Fixed z = INT2FIX(d);
    3922           0 :                                 z = gf_mulfix(z / 255, f_scale);
    3923           0 :                                 stack->mesh->vertices[w + h*txh->width].pos.z = z;
    3924             :                         }
    3925             :                 }
    3926           0 :                 stack->mesh->vbo_dirty = 1;
    3927             :         }
    3928             : #ifndef GPAC_DISABLE_VRML
    3929           0 :         if (tr_state->appear) txtrans = ((M_Appearance *)tr_state->appear)->textureTransform;
    3930             : #endif
    3931           0 :         tr_state->mesh_num_textures = gf_sc_texture_enable(txh, txtrans);
    3932           0 :         visual_3d_draw_mesh(tr_state, stack->mesh);
    3933           0 :         visual_3d_disable_texture(tr_state);
    3934             : 
    3935             : #endif //GPAC_USE_GLES1X
    3936             : 
    3937             : }
    3938             : 
    3939             : 
    3940             : 
    3941         178 : GF_Err compositor_3d_setup_fbo(u32 width, u32 height, u32 *fbo_id, u32 *tx_id, u32 *depth_id)
    3942             : {
    3943             : #if defined(GPAC_USE_GLES1X)
    3944             :         GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to setup FBO object: not supported on OpenGL ES 1.x\n"));
    3945             :         return GF_NOT_SUPPORTED;
    3946             : #else
    3947         178 :         if (! *tx_id) {
    3948         162 :                 glGenTextures(1, tx_id);
    3949             :         }
    3950         178 :         glBindTexture(GL_TEXTURE_2D, *tx_id);
    3951         178 :         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    3952         178 :         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    3953         178 :         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    3954         178 :         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    3955         178 :         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    3956             : 
    3957         178 :         if (! *fbo_id)
    3958         162 :                  glGenFramebuffers(1, fbo_id);
    3959             : 
    3960         178 :         glBindFramebuffer(GL_FRAMEBUFFER, *fbo_id);
    3961         178 :         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *tx_id, 0);
    3962             : 
    3963         178 :         if (! *depth_id)
    3964         162 :                 glGenRenderbuffers(1, depth_id);
    3965             : 
    3966         178 :         glBindRenderbuffer(GL_RENDERBUFFER, *depth_id);
    3967             : #if defined(GPAC_CONFIG_IOS) ||  defined(GPAC_CONFIG_ANDROID)
    3968             :         glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
    3969             : #else
    3970         178 :         glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
    3971             : #endif
    3972         178 :         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *depth_id);
    3973             : 
    3974         178 :         GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    3975         178 :         switch (status) {
    3976             :         case GL_FRAMEBUFFER_COMPLETE:
    3977             :                 break;
    3978           0 :         default:
    3979           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to setup FBO object: FBO status %08x\n", status));
    3980             :                 return GF_NOT_SUPPORTED;
    3981             :    }
    3982             : 
    3983         178 :         glBindFramebuffer(GL_FRAMEBUFFER, 0);
    3984         178 :         return GF_OK;
    3985             : #endif
    3986             : 
    3987             : }
    3988             : 
    3989        2351 : void compositor_3d_delete_fbo(u32 *fbo_id, u32 *fbo_tx_id, u32 *fbo_depth_id, Bool keep_tx_id)
    3990             : {
    3991             : #ifndef GPAC_USE_GLES1X
    3992        2351 :         if (*fbo_id) {
    3993         162 :                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
    3994         162 :                 glDeleteFramebuffers(1, fbo_id);
    3995         162 :                 *fbo_id = 0;
    3996             :         }
    3997        2351 :         if (*fbo_depth_id) {
    3998         162 :                 glDeleteRenderbuffers(1, fbo_depth_id);
    3999         162 :                 *fbo_depth_id = 0;
    4000             :         }
    4001        2351 :         if (*fbo_tx_id && !keep_tx_id) {
    4002         162 :                 glDeleteTextures(1, fbo_tx_id);
    4003         162 :                 *fbo_tx_id = 0;
    4004             :         }
    4005             : #endif
    4006        2351 : }
    4007             : 
    4008         122 : u32 compositor_3d_get_fbo_pixfmt()
    4009             : {
    4010         122 :         return GL_TEXTURE_2D;
    4011             : }
    4012             : 
    4013       15566 : void compositor_3d_enable_fbo(GF_Compositor *compositor, Bool enable)
    4014             : {
    4015             : #ifndef GPAC_USE_GLES1X
    4016       29108 :         glBindFramebuffer(GL_FRAMEBUFFER, enable ? compositor->fbo_id : 0);
    4017       15566 :         if (!enable)
    4018       14554 :                 glBindTexture(GL_TEXTURE_2D, 0);
    4019             : #endif
    4020             : 
    4021       15566 : }
    4022             : 
    4023        1907 : void visual_3d_clean_state(GF_VisualManager *visual)
    4024             : {
    4025        1907 :         glGetError();
    4026        1907 : }
    4027             : 
    4028             : #endif // GPAC_DISABLE_3D

Generated by: LCOV version 1.13