1 /*
2  *			GPAC - Multimedia Framework C SDK
3  *
4  *			Authors: Ivica Arsov, Jean Le Feuvre
5  *			Copyright (c) Mines-Telecom 2009-
6  *					All rights reserved
7  *
8  *  This file is part of GPAC / Wrapper
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 /*driver interfaces*/
27 #include <gpac/modules/video_out.h>
28 #include <gpac/list.h>
29 #include <gpac/constants.h>
30 
31 #include <gpac/setup.h>
32 
33 #ifdef GPAC_USE_GLES2
34 #include <GLES2/gl2.h>
35 #include <GLES2/gl2ext.h>
36 #else
37 #include <GLES/gl.h>
38 #include <GLES/glext.h>
39 #endif
40 
41 #ifdef PI
42 #undef PI
43 #endif
44 
45 #define PI 3.1415926535897932f
46 
47 /* Uncomment the next line if you want to debug */
48 /* #define DROID_EXTREME_LOGS */
49 
50 typedef struct
51 {
52 	u32 width, height;
53 	void * locked_data;
54 	u8 out_3d_type;
55 
56 	u32 tex_width, tex_height;
57 
58 	GLint texID;
59 
60 	GLubyte* texData;
61 
62 	u8 draw_texture;
63 	u8 non_power_two;
64 
65 	Bool fullscreen;
66 
67 	//Functions specific to OpenGL ES2
68 #ifdef GPAC_USE_GLES2
69 	GLuint base_vertex, base_fragment, base_program;
70 	GF_Matrix identity, ortho;
71 #endif
72 } AndroidContext;
73 
74 
75 #define RAW_OUT_PIXEL_FORMAT		GF_PIXEL_RGBA
76 #define NBPP						4
77 
78 #define RAWCTX	AndroidContext *rc = (AndroidContext *)dr->opaque
79 
80 
81 
82 //Functions specific to OpenGL ES2
83 #ifdef GPAC_USE_GLES2
84 
85 #define GF_TRUE 1
86 #define GF_FALSE 0
87 
88 
89 //we custom-define these instead of importing gl_inc.h
90 #define GL_COMPILE_STATUS 0x8B81
91 #define GL_FRAGMENT_SHADER 0x8B30
92 #define GL_INFO_LOG_LENGTH 0x8B84
93 #define GL_LINK_STATUS 0x8B82
94 #define GL_VERTEX_SHADER 0x8B31
95 
96 
97 
98 static char *glsl_vertex = "precision mediump float;\
99 	attribute vec4 gfVertex;\
100 	attribute vec4 gfTexCoord;\
101 	varying vec2 TexCoord;\
102 	uniform mat4 gfModelViewMatrix;\
103 	uniform mat4 gfProjectionMatrix;\
104 	void main(void){\
105 		vec4 gfEye;\
106 		gfEye = gfModelViewMatrix * gfVertex;\
107 		TexCoord = vec2(gfTexCoord);\
108 		gl_Position = gfProjectionMatrix * gfEye;\
109 	}";
110 
111 static char *glsl_fragment = "precision mediump float;\
112 	varying vec2 TexCoord;\
113 	uniform sampler2D img;\
114 	void main(void){\
115 		gl_FragColor = texture2D(img, TexCoord);\
116 	}";
117 
gl_check_error()118 static inline void gl_check_error()
119 {
120 	s32 res = glGetError();
121 	if (res) {
122 		GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE,
123 		       ("GL Error %d file %s line %d\n", res,
124 				__FILE__, __LINE__));
125 	}
126 }
127 
128 
gf_glGetUniformLocation(u32 glsl_program,const char * uniform_name)129 static GLint gf_glGetUniformLocation(u32 glsl_program, const char *uniform_name)
130 {
131 	GLint loc = glGetUniformLocation(glsl_program, uniform_name);
132 	if (loc<0) {
133 		GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[V3D:GLSL] Cannot find uniform \"%s\" in GLSL program\n", uniform_name));
134 	}
135 	return loc;
136 }
137 
gf_glGetAttribLocation(u32 glsl_program,const char * attrib_name)138 static GLint gf_glGetAttribLocation(u32 glsl_program, const char *attrib_name)
139 {
140 	GLint loc = glGetAttribLocation(glsl_program, attrib_name);
141 	if (loc<0) {
142 		GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[V3D:GLSL] Cannot find attrib \"%s\" in GLSL program\n", attrib_name));
143 	}
144 	return loc;
145 }
146 
147 //modified version of visual_3d_compile_shader function
compile_shader(u32 shader_id,const char * name,const char * source)148 Bool compile_shader(u32 shader_id, const char *name, const char *source) {
149 	GLint blen = 0;
150 	GLsizei slen = 0;
151 	u32 len;
152 	GLint is_compiled = 0;
153 
154 
155 	if(!source || !shader_id) return 0;
156 	len = (u32) strlen(source);
157 	glShaderSource(shader_id, 1, &source, &len);
158 	glCompileShader(shader_id);
159 
160 	glGetShaderiv(shader_id, GL_COMPILE_STATUS, &is_compiled);
161 	if (is_compiled == 1) return GF_TRUE;
162 
163 	glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH , &blen);
164 	if (blen > 1) {
165 		char* compiler_log = (char*) gf_malloc(blen);
166 		glGetShaderInfoLog(shader_id, blen, &slen, compiler_log);
167 		GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[GLSL] Failed to compile %s shader: %s\n", name, compiler_log));
168 		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[GLSL] ***** faulty shader code ****\n%s\n**********************\n", source));
169 		gf_free (compiler_log);
170 		return GF_FALSE;
171 	}
172 
173 	return GF_TRUE;
174 }
175 
176 
initGLES2(AndroidContext * rc)177 static Bool initGLES2(AndroidContext *rc) {
178 
179 
180 //PRINT OpengGL INFO
181 	char* ext;
182 
183 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android InitGLES2"));
184 
185 	ext = (char*)glGetString(GL_VENDOR);
186 	GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("OpenGL ES Vendor: %s", ext));
187 
188 	ext = (char*)glGetString(GL_RENDERER);
189 	GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("OpenGL ES Renderer: %s", ext));
190 
191 	ext = (char*)glGetString(GL_VERSION);
192 	GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("OpenGL ES Version: %s", ext));
193 
194 	ext = (char*)glGetString(GL_EXTENSIONS);
195 	GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("OpenGL ES Extensions: %s", ext));
196 
197 
198 
199 //Generic GL setup
200 	/* Set the background black */
201 	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
202 
203 	/* Depth buffer setup */
204 	glClearDepthf(1.0f);
205 
206 	/* Enables Depth Testing */
207 	glEnable(GL_DEPTH_TEST);
208 
209 	/* The Type Of Depth Test To Do */
210 	glDepthFunc(GL_LEQUAL);
211 
212 
213 //Shaders setup
214 	Bool res = GF_FALSE;
215 	GLint linked;
216 
217 	gl_check_error();
218 	gf_mx_init(rc->identity);
219 	rc->base_program = glCreateProgram();
220 	rc->base_vertex = glCreateShader(GL_VERTEX_SHADER);
221 	rc->base_fragment = glCreateShader(GL_FRAGMENT_SHADER);
222 
223 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Compiling shaders"));
224 	res = compile_shader(rc->base_vertex, "vertex", glsl_vertex);
225 	if(!res) return GF_FALSE;
226 	res = compile_shader(rc->base_fragment, "fragment", glsl_fragment);
227 	if(!res) return GF_FALSE;
228 
229 	glAttachShader(rc->base_program, rc->base_vertex);
230 	glAttachShader(rc->base_program, rc->base_fragment);
231 	glLinkProgram(rc->base_program);
232 
233 	glGetProgramiv(rc->base_program, GL_LINK_STATUS, &linked);
234 	if (!linked) {
235 		int i32CharsWritten, i32InfoLogLength;
236 		char pszInfoLog[2048];
237 		glGetProgramiv(rc->base_program, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
238 		glGetProgramInfoLog(rc->base_program, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
239 		GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, (pszInfoLog));
240 		return GF_FALSE;
241 	}
242 	glUseProgram(rc->base_program);
243 	gl_check_error();
244 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Shaders compiled"))
245 
246 	return GF_TRUE;
247 }
248 
load_matrix_shaders(GLuint program,Fixed * mat,const char * name)249 static void load_matrix_shaders(GLuint program, Fixed *mat, const char *name)
250 {
251 	GLint loc;
252 #ifdef GPAC_FIXED_POINT
253 	Float _mat[16];
254 	u32 i;
255 #endif
256 	gl_check_error();
257 	loc = glGetUniformLocation(program, name);
258 	if(loc<0) {
259 		GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("GL Error (file %s line %d): Invalid matrix name", __FILE__, __LINE__));
260 		return;
261 	}
262 	gl_check_error();
263 
264 #ifdef GPAC_FIXED_POINT
265 	for (i=0; i<16; i++) _mat[i] = FIX2FLT(mat[i]);
266 	glUniformMatrix4fv(loc, 1, GL_FALSE, (GLfloat *) _mat);
267 #else
268 	glUniformMatrix4fv(loc, 1, GL_FALSE, mat);
269 #endif
270 	gl_check_error();
271 }
272 
273 
274 //ES2 version of glOrthox() - resulting matrix is stored in rc->ortho
275 //more info on Orthographic projection matrix at http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho
calculate_ortho(Fixed left,Fixed right,Fixed bottom,Fixed top,Fixed near,Fixed far,AndroidContext * rc)276 static void calculate_ortho(Fixed left, Fixed right, Fixed bottom, Fixed top, Fixed near, Fixed far,  AndroidContext *rc) {
277 
278 
279 	if((left==right)|(bottom==top)|(near==far)) {
280 		GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("GL Error (file %s line %d): Invalid Orthogonal projection values", __FILE__, __LINE__));
281 		return;
282 	}
283 
284 	gf_mx_init(rc->ortho);
285 
286 //For Orthographic Projection
287 	rc->ortho.m[0] = gf_divfix(2, (right-left));
288 	rc->ortho.m[5] = gf_divfix(2, (top-bottom));
289 	rc->ortho.m[10] = gf_divfix(-2, far-near);
290 	rc->ortho.m[12] = -gf_divfix(right+left, right-left);
291 	rc->ortho.m[13] = -gf_divfix(top+bottom, top-bottom);
292 	rc->ortho.m[14] = -gf_divfix(far+near, far-near);
293 	rc->ortho.m[15] = FIX_ONE;
294 }
295 
296 
297 
298 #endif	//Endof specifix for GLES2 (ifdef GPAC_USE_GLES2)
299 
300 
301 #ifndef GPAC_USE_GLES2
initGL(AndroidContext * rc)302 void initGL(AndroidContext *rc)
303 {
304 	char* ext;
305 
306 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android InitGL"));
307 
308 	ext = (char*)glGetString(GL_VENDOR);
309 	GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("OpenGL ES Vendor: %s", ext));
310 
311 	ext = (char*)glGetString(GL_RENDERER);
312 	GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("OpenGL ES Renderer: %s", ext));
313 
314 	ext = (char*)glGetString(GL_VERSION);
315 	GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("OpenGL ES Version: %s", ext));
316 
317 	ext = (char*)glGetString(GL_EXTENSIONS);
318 	GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("OpenGL ES Extensions: %s", ext));
319 
320 	if ( strstr(ext, "GL_OES_draw_texture") )
321 	{
322 		rc->draw_texture = 1;
323 		GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("Using GL_OES_draw_texture"));
324 	}
325 	if ( strstr(ext, "GL_ARB_texture_non_power_of_two") )
326 	{
327 		rc->non_power_two = 0;
328 		GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("Using GL_ARB_texture_non_power_of_two"));
329 	}
330 
331 	/* Enable smooth shading */
332 	glShadeModel(GL_SMOOTH);
333 
334 	/* Set the background black */
335 	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
336 
337 	/* Depth buffer setup */
338 	glClearDepthf(1.0f);
339 
340 	/* Enables Depth Testing */
341 	glEnable(GL_DEPTH_TEST);
342 
343 	/* The Type Of Depth Test To Do */
344 	glDepthFunc(GL_LEQUAL);
345 
346 	/* Really Nice Perspective Calculations */
347 	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
348 }
349 #endif
350 
gluPerspective(GLfloat fovy,GLfloat aspect,GLfloat zNear,GLfloat zFar)351 void gluPerspective(GLfloat fovy, GLfloat aspect,
352                     GLfloat zNear, GLfloat zFar)
353 {
354 #ifndef GPAC_USE_GLES2
355 	GLfloat xmin, xmax, ymin, ymax;
356 
357 	ymax = zNear * (GLfloat)tan(fovy * PI / 360);
358 	ymin = -ymax;
359 	xmin = ymin * aspect;
360 	xmax = ymax * aspect;
361 	glFrustumx((GLfixed)(xmin * 65536), (GLfixed)(xmax * 65536),
362 	           (GLfixed)(ymin * 65536), (GLfixed)(ymax * 65536),
363 	           (GLfixed)(zNear * 65536), (GLfixed)(zFar * 65536));
364 #endif
365 }
366 
resizeWindow(AndroidContext * rc)367 void resizeWindow(AndroidContext *rc)
368 {
369 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("resizeWindow : start"));
370 
371 	/* Protect against a divide by zero */
372 	if (rc->height==0)
373 		rc->height = 1;
374 
375 	/* Setup our viewport. */
376 	glViewport(0, 0, (GLsizei)rc->width, (GLsizei)rc->height);
377 #ifndef GPAC_USE_GLES2
378 	/* change to the projection matrix and set our viewing volume. */
379 	glMatrixMode(GL_PROJECTION);
380 	glLoadIdentity();
381 
382 	/* Set our perspective */
383 	glOrthox(0, INT2FIX(rc->width), 0, INT2FIX(rc->height), INT2FIX(-1), INT2FIX(1));
384 
385 	/* Make sure we're chaning the model view and not the projection */
386 	glMatrixMode(GL_MODELVIEW);
387 
388 	/* Reset The View */
389 	glLoadIdentity();
390 #else
391 	gl_check_error();
392 	glUseProgram(rc->base_program);
393 	calculate_ortho(0, INT2FIX(rc->width), 0, INT2FIX(rc->height), INT2FIX(-1), INT2FIX(1), rc);
394 	load_matrix_shaders(rc->base_program, (Fixed *) rc->ortho.m, "gfProjectionMatrix");
395 	load_matrix_shaders(rc->base_program, (Fixed *) rc->identity.m, "gfModelViewMatrix");
396 	gl_check_error();
397 #endif
398 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("resizeWindow : end"));
399 }
400 
drawGLScene(AndroidContext * rc)401 void drawGLScene(AndroidContext *rc)
402 {
403 #ifdef DROID_EXTREME_LOGS
404 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("drawGLScene : start"));
405 #endif /* DROID_EXTREME_LOGS */
406 #ifdef GPAC_USE_GLES2
407 	GLint loc_vertex_array, loc_texcoord_array;
408 #endif
409 
410 	GLfloat vertices[4][3];
411 	GLfloat texcoord[4][2];
412 //	int i, j;
413 
414 #ifndef GPAC_USE_GLES2
415 	float rgba[4];
416 #endif
417 	gl_check_error();
418 
419 	// Reset states
420 #ifndef GPAC_USE_GLES2
421 	rgba[0] = rgba[1] = rgba[2] = 0.f;
422 	rgba[0] = 1.f;
423 	glColor4f(1.f, 1.f, 1.f, 1.f);
424 	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, rgba);
425 	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, rgba);
426 	glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, rgba);
427 #endif
428 	/* Clear The Screen And The Depth Buffer */
429 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
430 	gl_check_error();
431 	//glEnable(GL_BLEND);
432 	//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
433 #ifndef GPAC_USE_GLES2
434 	glEnable(GL_TEXTURE_2D);
435 #endif
436 	glUseProgram(rc->base_program);
437 	glActiveTexture(GL_TEXTURE0);
438 	glBindTexture( GL_TEXTURE_2D, rc->texID);
439 	gl_check_error();
440 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
441 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
442 #ifndef GPAC_USE_GLES2
443 	glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
444 #endif
445 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
446 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
447 
448 //    for ( i = 0; i < rc->height/2; i++ )
449 //    	for ( j = 0; j < rc->width; j++ )
450 //    		rc->texData[ i*rc->width*NBPP + j*NBPP + 3] = 200;
451 
452 //    memset(rc->texData, 255, 4 * rc->width * rc->height );
453 
454 	glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, rc->tex_width, rc->tex_height, 0,
455 	              GL_RGBA, GL_UNSIGNED_BYTE, rc->texData );
456 
457 	gl_check_error();
458 	if ( rc->draw_texture )
459 	{
460 #ifndef GPAC_USE_GLES2
461 		gl_check_error();
462 		int cropRect[4] = {0,rc->height,rc->width,-rc->height};
463 		glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
464 		glDrawTexsOES(0, 0, 0, rc->width, rc->height);
465 #endif
466 	}
467 	else
468 	{
469 		gl_check_error();
470 
471 #ifndef GPAC_USE_GLES2
472 		/* Enable VERTEX array */
473 		glEnableClientState(GL_VERTEX_ARRAY);
474 		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
475 
476 		/* Setup pointer to  VERTEX array */
477 		glVertexPointer(3, GL_FLOAT, 0, vertices);
478 		glTexCoordPointer(2, GL_FLOAT, 0, texcoord);
479 
480 		/* Move Left 1.5 Units And Into The Screen 6.0 */
481 		glLoadIdentity();
482 #else
483 		loc_vertex_array = glGetAttribLocation(rc->base_program, "gfVertex");
484 		if(loc_vertex_array<0)
485 			return;
486 		glEnableVertexAttribArray(loc_vertex_array);
487 		glVertexAttribPointer(loc_vertex_array, 3, GL_FLOAT, GL_FALSE, 0, vertices);
488 
489 		loc_texcoord_array = glGetAttribLocation(rc->base_program, "gfTexCoord");
490 		if (loc_texcoord_array>=0) {
491 			glVertexAttribPointer(loc_texcoord_array, 2, GL_FLOAT, GL_FALSE, 0, texcoord);
492 			glEnableVertexAttribArray(loc_texcoord_array);
493 		}
494 
495 
496 #endif
497 		//glTranslatef(0.0f, 0.0f, -3.3f);
498 		//glTranslatef(0.0f, 0.0f, -2.3f);
499 
500 		/* Top Right Of The Quad    */
501 		vertices[0][0]=rc->tex_width;
502 		vertices[0][1]=rc->tex_height;
503 		vertices[0][2]=0.0f;
504 		texcoord[0][0]=1.f;
505 		texcoord[0][1]=0.f;
506 		/* Top Left Of The Quad     */
507 		vertices[1][0]=0.f;
508 		vertices[1][1]=rc->tex_height;
509 		vertices[1][2]=0.0f;
510 		texcoord[1][0]=0.f;
511 		texcoord[1][1]=0.f;
512 		/* Bottom Left Of The Quad  */
513 		vertices[2][0]=rc->tex_width;
514 		vertices[2][1]=0.f;
515 		vertices[2][2]=0.0f;
516 		texcoord[2][0]=1.f;
517 		texcoord[2][1]=1.f;
518 		/* Bottom Right Of The Quad */
519 		vertices[3][0]=0.f;
520 		vertices[3][1]=0.f;
521 		vertices[3][2]=0.0f;
522 		texcoord[3][0]=0.f;
523 		texcoord[3][1]=1.f;
524 
525 		/* Drawing using triangle strips, draw triangles using 4 vertices */
526 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
527 #ifndef GPAC_USE_GLES2
528 		/* Disable vertex array */
529 		glDisableClientState(GL_VERTEX_ARRAY);
530 		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
531 #endif
532 	}
533 #ifndef GPAC_USE_GLES2
534 	glDisable(GL_TEXTURE_2D);
535 #endif
536 	gl_check_error();
537 
538 	/* Flush all drawings */
539 	glFinish();
540 #ifdef DROID_EXTREME_LOGS
541 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("drawGLScene : end"));
542 #endif /* DROID_EXTREME_LOGS */
543 }
544 
releaseTexture(AndroidContext * rc)545 int releaseTexture(AndroidContext *rc)
546 {
547 	gl_check_error();
548 	if (!rc)
549 		return 0;
550 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android Delete Texture"));
551 
552 	if ( rc->texID >= 0)
553 	{
554 		glDeleteTextures(1, &(rc->texID));
555 		rc->texID = -1;
556 	}
557 	if (rc->texData)
558 	{
559 		gf_free(rc->texData);
560 		rc->texData = NULL;
561 	}
562 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android Delete Texture DONE"))
563 	gl_check_error();
564 	return 0;
565 }
566 
createTexture(AndroidContext * rc)567 int createTexture(AndroidContext *rc)
568 {
569 	if (!rc)
570 		return 0;
571 	if ( rc->texID >= 0 )
572 		releaseTexture(rc);
573 
574 	GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("Android Create Texture Size: WxH: %dx%d", rc->tex_width, rc->tex_height));
575 
576 	glGenTextures( 1, &(rc->texID) );
577 
578 	rc->texData = (GLubyte*)gf_malloc( 4 * rc->tex_width * rc->tex_height );
579 	memset(rc->texData, 255, 4 * rc->tex_width * rc->tex_height );
580 	//memset(data, 0, 4 * width * height/2 );
581 
582 	glBindTexture( GL_TEXTURE_2D, rc->texID);
583 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
584 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
585 #ifndef GPAC_USE_GLES2
586 	glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
587 #endif
588 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
589 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
590 
591 	glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, rc->tex_width, rc->tex_height, 0,
592 	              GL_RGBA, GL_UNSIGNED_BYTE, NULL/*rc->texData*/ );
593 
594 	glBindTexture( GL_TEXTURE_2D, 0);
595 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android Create Texture DONE"));
596 	return 0;
597 }
598 
599 
find_pow_2(u32 num)600 u32 find_pow_2(u32 num)
601 {
602 	u32 res = 1;
603 	while (res < num)
604 		res *= 2;
605 	return res;
606 }
607 
droid_Resize(GF_VideoOutput * dr,u32 w,u32 h)608 static GF_Err droid_Resize(GF_VideoOutput *dr, u32 w, u32 h)
609 {
610 	RAWCTX;
611 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android Resize: %dx%d", w, h));
612 
613 	rc->width = w;
614 	rc->height = h;
615 
616 	if ((dr->max_screen_width < w) || (dr->max_screen_height < h)) {
617 		dr->max_screen_width = w;
618 		dr->max_screen_height = h;
619 	}
620 	//npot textures are supported in ES2
621 #ifdef GPAC_USE_GLES2
622 	rc->tex_width = rc->width;
623 	rc->tex_height = rc->height;
624 #else
625 	if ( rc->non_power_two )
626 	{
627 		rc->tex_width = rc->width;
628 		rc->tex_height = rc->height;
629 	}
630 	else
631 	{
632 		rc->tex_width = find_pow_2(rc->width);
633 		rc->tex_height = find_pow_2(rc->height);
634 	}
635 #endif
636 	gl_check_error();
637 	resizeWindow(rc);
638 
639 	if ( rc->out_3d_type == 0 )
640 	{
641 		createTexture(rc);
642 	}
643 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android Resize DONE", w, h));
644 	gl_check_error();
645 	return GF_OK;
646 }
647 
droid_Setup(GF_VideoOutput * dr,void * os_handle,void * os_display,u32 init_flags)648 GF_Err droid_Setup(GF_VideoOutput *dr, void *os_handle, void *os_display, u32 init_flags)
649 {
650 	RAWCTX;
651 
652 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android Setup: %d", init_flags));
653 
654 
655 #ifdef GPAC_USE_GLES2
656 
657 	if ( rc->out_3d_type == 0 ) {
658 		Bool res = GF_FALSE;
659 		GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("We are in OpenGL: disable mode"));
660 		res = initGLES2(rc);
661 		if(res==GF_FALSE) {
662 			GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("ERROR Compiling ES2 Shaders"));
663 		} else {	//set texture
664 			glUseProgram(rc->base_program);
665 			GLint loc = gf_glGetUniformLocation(rc->base_program, "img");
666 			glUniform1i(loc,0);
667 		}
668 	}
669 
670 #else
671 
672 	if ( rc->out_3d_type == 0 )
673 
674 		initGL(rc);
675 #endif //GPAC_USE_GLES2
676 
677 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android Setup DONE"));
678 	return GF_OK;
679 }
680 
681 
droid_Shutdown(GF_VideoOutput * dr)682 static void droid_Shutdown(GF_VideoOutput *dr)
683 {
684 	RAWCTX;
685 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android Shutdown\n"));
686 
687 	releaseTexture(rc);
688 
689 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android Shutdown DONE"));
690 }
691 
692 
droid_Flush(GF_VideoOutput * dr,GF_Window * dest)693 static GF_Err droid_Flush(GF_VideoOutput *dr, GF_Window *dest)
694 {
695 	RAWCTX;
696 #ifdef DROID_EXTREME_LOGS
697 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android Flush\n"));
698 #endif /* DROID_EXTREME_LOGS */
699 
700 	if ( rc->out_3d_type == 0 )
701 		drawGLScene(rc);
702 #ifdef DROID_EXTREME_LOGS
703 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android Flush DONE"));
704 #endif /* DROID_EXTREME_LOGS */
705 	return GF_OK;
706 }
707 
droid_LockBackBuffer(GF_VideoOutput * dr,GF_VideoSurface * vi,Bool do_lock)708 static GF_Err droid_LockBackBuffer(GF_VideoOutput *dr, GF_VideoSurface *vi, Bool do_lock)
709 {
710 	RAWCTX;
711 #ifdef DROID_EXTREME_LOGS
712 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android LockBackBuffer: %d", do_lock));
713 #endif /* DROID_EXTREME_LOGS */
714 	if (do_lock) {
715 		if (!vi) return GF_BAD_PARAM;
716 
717 		if ( rc->out_3d_type != 0 )
718 			return GF_NOT_SUPPORTED;
719 
720 		memset(vi, 0, sizeof(GF_VideoSurface));
721 		vi->height = rc->height;
722 		vi->width = rc->width;
723 		vi->video_buffer = rc->texData;
724 		vi->is_hardware_memory = 0;
725 		vi->pitch_x = NBPP;
726 		vi->pitch_y = NBPP * rc->tex_width;
727 		vi->pixel_format = RAW_OUT_PIXEL_FORMAT;
728 	}
729 	else
730 	{
731 		if (rc->locked_data)
732 		{
733 			//glBindTexture( GL_TEXTURE_2D, rc->texID);
734 			//glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
735 			//glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
736 
737 			//glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, rc->width, rc->height, 0,
738 			//			GL_RGBA, GL_UNSIGNED_BYTE, rc->locked_data );
739 		}
740 	}
741 #ifdef DROID_EXTREME_LOGS
742 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android LockBackBuffer DONE"));
743 #endif /* DROID_EXTREME_LOGS */
744 	return GF_OK;
745 }
746 
droid_ProcessEvent(GF_VideoOutput * dr,GF_Event * evt)747 static GF_Err droid_ProcessEvent(GF_VideoOutput *dr, GF_Event *evt)
748 {
749 	RAWCTX;
750 
751 	if (!evt) return GF_OK;
752 
753 	switch (evt->type) {
754 	case GF_EVENT_SIZE:
755 		GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("GF_EVENT_SIZE( %d x %d)", evt->setup.width, evt->setup.height));
756 		//in fullscreen mode: do not change viewport; just update perspective
757 		if (rc->fullscreen) {
758 #ifdef GPAC_USE_GLES2
759 			gl_check_error();
760 			glUseProgram(rc->base_program);
761 			calculate_ortho(0, INT2FIX(rc->width), 0, INT2FIX(rc->height), INT2FIX(-1), INT2FIX(1), rc);
762 			load_matrix_shaders(rc->base_program, (Fixed *) rc->ortho.m, "gfProjectionMatrix");
763 			load_matrix_shaders(rc->base_program, (Fixed *) rc->identity.m, "gfModelViewMatrix");
764 			gl_check_error();
765 #else
766 			/* change to the projection matrix and set our viewing volume. */
767 			glMatrixMode(GL_PROJECTION);
768 			glLoadIdentity();
769 
770 			/* Set our perspective */
771 			glOrthox(0, INT2FIX(rc->width), 0, INT2FIX(rc->height), INT2FIX(-1), INT2FIX(1));
772 
773 			/* Make sure we're chaning the model view and not the projection */
774 			glMatrixMode(GL_MODELVIEW);
775 
776 			/* Reset The View */
777 			glLoadIdentity();
778 #endif
779 			return GF_OK;
780 		} else
781 			return droid_Resize(dr, evt->setup.width, evt->setup.height);
782 
783 	case GF_EVENT_VIDEO_SETUP:
784 		GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android OpenGL mode: %d", evt->setup.use_opengl));
785 		if (!evt->setup.use_opengl) {
786 			rc->out_3d_type = 0;
787 //					initGL(rc);
788 			droid_Resize(dr, evt->setup.width, evt->setup.height);
789 		} else {
790 			rc->out_3d_type = 1;
791 			droid_Resize(dr, evt->setup.width, evt->setup.height);
792 		}
793 		return GF_OK;
794 
795 	case GF_EVENT_SET_CURSOR:
796 		GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("GF_EVENT_SET_CURSOR"));
797 		return GF_OK;
798 	case GF_EVENT_SET_CAPTION:
799 		GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("GF_EVENT_SET_CAPTION"));
800 		return GF_OK;
801 	case GF_EVENT_SHOWHIDE:
802 		GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("GF_EVENT_SHOWHIDE"));
803 		return GF_OK;
804 	default:
805 		GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Process Unknown Event: %d", evt->type));
806 		return GF_OK;
807 
808 	case GF_EVENT_TEXT_EDITING_START:
809 	case GF_EVENT_TEXT_EDITING_END:
810 		return GF_NOT_SUPPORTED;
811 	}
812 	return GF_OK;
813 }
814 
droid_SetFullScreen(GF_VideoOutput * dr,Bool bOn,u32 * outWidth,u32 * outHeight)815 static GF_Err droid_SetFullScreen(GF_VideoOutput *dr, Bool bOn, u32 *outWidth, u32 *outHeight)
816 {
817 	RAWCTX;;
818 
819 	*outWidth = dr->max_screen_width;
820 	*outHeight = dr->max_screen_height;
821 	rc->fullscreen = bOn;
822 	return droid_Resize(dr, dr->max_screen_width, dr->max_screen_height);
823 }
824 
NewAndroidVideoOutput()825 GF_VideoOutput *NewAndroidVideoOutput()
826 {
827 	AndroidContext *pCtx;
828 	GF_VideoOutput *driv = (GF_VideoOutput *) gf_malloc(sizeof(GF_VideoOutput));
829 	GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("Android Video Initialization in progress..."));
830 	memset(driv, 0, sizeof(GF_VideoOutput));
831 	GF_REGISTER_MODULE_INTERFACE(driv, GF_VIDEO_OUTPUT_INTERFACE, "Android Video Output", "gpac distribution")
832 
833 	pCtx = gf_malloc(sizeof(AndroidContext));
834 	memset(pCtx, 0, sizeof(AndroidContext));
835 
836 	pCtx->texID = -1;
837 	driv->opaque = pCtx;
838 
839 	driv->Flush = droid_Flush;
840 	driv->LockBackBuffer = droid_LockBackBuffer;
841 	driv->Setup = droid_Setup;
842 	driv->Shutdown = droid_Shutdown;
843 	driv->ProcessEvent = droid_ProcessEvent;
844 	driv->SetFullScreen = droid_SetFullScreen;
845 
846 	driv->max_screen_width = 1024;
847 	driv->max_screen_height = 1024;
848 
849 	driv->hw_caps = GF_VIDEO_HW_OPENGL;// | GF_VIDEO_HW_OPENGL_OFFSCREEN_ALPHA;//GF_VIDEO_HW_DIRECT_ONLY;//
850 
851 	GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("Android Video Init Done.\n"));
852 	return (void *)driv;
853 }
854 
DeleteAndroidVideoOutput(void * ifce)855 void DeleteAndroidVideoOutput(void *ifce)
856 {
857 	AndroidContext *rc;
858 	GF_VideoOutput *driv = (GF_VideoOutput *) ifce;
859 	if (!ifce)
860 		return;
861 	droid_Shutdown(driv);
862 	rc = (AndroidContext *)driv->opaque;
863 	if (rc)
864 		gf_free(rc);
865 	driv->opaque = NULL;
866 	gf_free(driv);
867 	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("Android vout deinit\n"));
868 }
869 
870 /*interface query*/
871 GPAC_MODULE_EXPORT
QueryInterfaces()872 const u32 *QueryInterfaces()
873 {
874 	static u32 si [] = {
875 		GF_VIDEO_OUTPUT_INTERFACE,
876 		0
877 	};
878 	return si;
879 }
880 /*interface create*/
881 GPAC_MODULE_EXPORT
LoadInterface(u32 InterfaceType)882 GF_BaseInterface *LoadInterface(u32 InterfaceType)
883 {
884 	if (InterfaceType == GF_VIDEO_OUTPUT_INTERFACE) return (GF_BaseInterface *) NewAndroidVideoOutput();
885 	return NULL;
886 }
887 /*interface destroy*/
888 GPAC_MODULE_EXPORT
ShutdownInterface(GF_BaseInterface * ifce)889 void ShutdownInterface(GF_BaseInterface *ifce)
890 {
891 	switch (ifce->InterfaceType) {
892 	case GF_VIDEO_OUTPUT_INTERFACE:
893 		DeleteAndroidVideoOutput((GF_VideoOutput *)ifce);
894 		break;
895 	}
896 }
897 
898 GPAC_MODULE_STATIC_DECLARATION( droid_vidgl )
899