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