<commit_before>/*
 *			GPAC - Multimedia Framework C SDK
 *
 *			Authors: <NAME>, <NAME>
 *			Copyright (c) Mines-Telecom 2009-
 *					All rights reserved
 *
 *  This file is part of GPAC / Wrapper
 *
 *  GPAC is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  GPAC is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

/*driver interfaces*/
#include <gpac/modules/video_out.h>
#include <gpac/list.h>
#include <gpac/constants.h>

#include <gpac/setup.h>

#ifdef GPAC_USE_GLES2
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#else
#include <GLES/gl.h>
#include <GLES/glext.h>
#endif

#include <android/log.h>

#ifdef GPAC_USE_GLES2
#define TAG "DROID_VIDEO [GLES2]"
#else
#define TAG "DROID_VIDEO"
#endif

#define LOG   __android_log_print

#ifdef PI
#undef PI
#endif

#define PI 3.1415926535897932f

/* Uncomment the next line if you want to debug */
/* #define DROID_EXTREME_LOGS */

typedef struct
{
	u32 width, height;
	void * locked_data;
	u8 out_3d_type;

	u32 tex_width, tex_height;

	GLuint texID;
	GLuint framebuff;
	GLuint depthbuff;

	GLubyte* texData;

	u8 draw_texture;
	u8 non_power_two;

	Bool fullscreen;

	//Functions specific to OpenGL ES2
	#ifdef GPAC_USE_GLES2
	GLuint base_vertex, base_fragment, base_program;
	GF_Matrix identity, ortho;
	#endif
} AndroidContext;


#define RAW_OUT_PIXEL_FORMAT		GF_PIXEL_RGBA
#define NBPP						4

#define RAWCTX	AndroidContext *rc = (AndroidContext *)dr->opaque



//Functions specific to OpenGL ES2
#ifdef GPAC_USE_GLES2

#define GF_TRUE 1
#define GF_FALSE 0


//we custom-define these instead of importing gl_inc.h
#define GL_COMPILE_STATUS 0x8B81
#define GL_FRAGMENT_SHADER 0x8B30
#define GL_INFO_LOG_LENGTH 0x8B84
#define GL_LINK_STATUS 0x8B82
#define GL_VERTEX_SHADER 0x8B31



static char *glsl_vertex = "precision mediump float;\
	attribute vec4 gfVertex;\
	attribute vec4 gfTexCoord;\
	varying vec2 TexCoord;\
	uniform mat4 gfModelViewMatrix;\
	uniform mat4 gfProjectionMatrix;\
	void main(void){\
		vec4 gfEye;\
		gfEye = gfModelViewMatrix * gfVertex;\
		TexCoord = vec2(gfTexCoord);\
		gl_Position = gfProjectionMatrix * gfEye;\
	}";

static char *glsl_fragment = "precision mediump float;\
	varying vec2 TexCoord;\
	uniform sampler2D img;\
	void main(void){\
		gl_FragColor = texture2D(img, TexCoord);\
	}";

#define GL_CHECK_ERR {s32 res = glGetError(); if (res) GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("GL Error %d file %s line %d\n", res, __FILE__, __LINE__)); }

static GLint gf_glGetUniformLocation(u32 glsl_program, const char *uniform_name)
{
	GLint loc = glGetUniformLocation(glsl_program, uniform_name);
	if (loc<0) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[V3D:GLSL] Cannot find uniform \"%s\" in GLSL program\n", uniform_name));
	}
	return loc;
}

static GLint gf_glGetAttribLocation(u32 glsl_program, const char *attrib_name)
{
	GLint loc = glGetAttribLocation(glsl_program, attrib_name);
	if (loc<0) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[V3D:GLSL] Cannot find attrib \"%s\" in GLSL program\n", attrib_name));
	}
	return loc;
}

//modified version of visual_3d_compile_shader function
Bool compile_shader(u32 shader_id, const char *name, const char *source){
	GLint blen = 0;
	GLsizei slen = 0;
	u32 len;
	GLint is_compiled = 0;


	if(!source || !shader_id) return 0;
	len = (u32) strlen(source);
	glShaderSource(shader_id, 1, &source, &len);
	glCompileShader(shader_id);

	glGetShaderiv(shader_id, GL_COMPILE_STATUS, &is_compiled);
	if (is_compiled == 1) return GF_TRUE;

	glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH , &blen);
	if (blen > 1) {
		char* compiler_log = (char*) gf_malloc(blen);
		glGetShaderInfoLog(shader_id, blen, &slen, compiler_log);
		GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[GLSL] Failed to compile %s shader: %s\n", name, compiler_log));
		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[GLSL] ***** faulty shader code ****\n%s\n**********************\n", source));
		gf_free (compiler_log);
		return GF_FALSE;
	}

	return GF_TRUE;
}


static Bool initGLES2(AndroidContext *rc){


//PRINT OpengGL INFO
	char* ext;

	LOG( ANDROID_LOG_DEBUG, TAG, "Android InitGLES2");

	ext = (char*)glGetString(GL_VENDOR);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Vendor: %s", ext);

	ext = (char*)glGetString(GL_RENDERER);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Renderer: %s", ext);

	ext = (char*)glGetString(GL_VERSION);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Version: %s", ext);

	ext = (char*)glGetString(GL_EXTENSIONS);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Extensions: %s", ext);



//Generic GL setup
	/* Set the background black */
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	/* Depth buffer setup */
	glClearDepthf(1.0f);

	/* Enables Depth Testing */
	glEnable(GL_DEPTH_TEST);

	/* The Type Of Depth Test To Do */
	glDepthFunc(GL_LEQUAL);


//Shaders setup
	Bool res = GF_FALSE;
	GLint linked;

	GL_CHECK_ERR
	gf_mx_init(rc->identity);
	rc->base_program = glCreateProgram();
	rc->base_vertex = glCreateShader(GL_VERTEX_SHADER);
	rc->base_fragment = glCreateShader(GL_FRAGMENT_SHADER);

	LOG( ANDROID_LOG_DEBUG, TAG, ("Compiling shaders"));
	res = compile_shader(rc->base_vertex, "vertex", glsl_vertex);
	if(!res) return GF_FALSE;
	res = compile_shader(rc->base_fragment, "fragment", glsl_fragment);
	if(!res) return GF_FALSE;

	glAttachShader(rc->base_program, rc->base_vertex);
	glAttachShader(rc->base_program, rc->base_fragment);
	glLinkProgram(rc->base_program);

	glGetProgramiv(rc->base_program, GL_LINK_STATUS, &linked);
	if (!linked) {
		int i32CharsWritten, i32InfoLogLength;
		char pszInfoLog[2048];
		glGetProgramiv(rc->base_program, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
		glGetProgramInfoLog(rc->base_program, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
		GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, (pszInfoLog));
		return GF_FALSE;
	}
	glUseProgram(rc->base_program);
	GL_CHECK_ERR
	LOG( ANDROID_LOG_DEBUG, TAG, "Shaders compiled");

	return GF_TRUE;
}

static void load_matrix_shaders(GLuint program, Fixed *mat, const char *name)
{
	GLint loc=-1;
#ifdef GPAC_FIXED_POINT
	Float _mat[16];
	u32 i;
#endif
GL_CHECK_ERR
	loc = glGetUniformLocation(program, name);
	if(loc<0){
		GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("GL Error (file %s line %d): Invalid matrix name", __FILE__, __LINE__));
		return;
	}
	GL_CHECK_ERR

#ifdef GPAC_FIXED_POINT
	for (i=0; i<16;i++) _mat[i] = FIX2FLT(mat[i]);
	glUniformMatrix4fv(loc, 1, GL_FALSE, (GLfloat *) _mat);
#else
	glUniformMatrix4fv(loc, 1, GL_FALSE, mat);
#endif
	GL_CHECK_ERR
}


//ES2 version of glOrthox() - resulting matrix is stored in rc->ortho
//more info on Orthographic projection matrix at http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho
static void calculate_ortho(Fixed left, Fixed right, Fixed bottom, Fixed top, Fixed near, Fixed far,  AndroidContext *rc){


	if((left==right)|(bottom==top)|(near==far)){
		GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("GL Error (file %s line %d): Invalid Orthogonal projection values", __FILE__, __LINE__));
		return;
	}

	gf_mx_init(rc->ortho);

//For Orthographic Projection
	rc->ortho.m[0] = gf_divfix(2, (right-left));
	rc->ortho.m[5] = gf_divfix(2, (top-bottom));
	rc->ortho.m[10] = gf_divfix(-2, far-near);
	rc->ortho.m[12] = -gf_divfix(right+left, right-left);
	rc->ortho.m[13] = -gf_divfix(top+bottom, top-bottom);
	rc->ortho.m[14] = -gf_divfix(far+near, far-near);
	rc->ortho.m[15] = FIX_ONE;
}



#endif	//Endof specifix for GLES2 (ifdef GPAC_USE_GLES2)


#ifndef GPAC_USE_GLES2
void initGL(AndroidContext *rc)
{
	char* ext;

	LOG( ANDROID_LOG_DEBUG, TAG, "Android InitGL");

	ext = (char*)glGetString(GL_VENDOR);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Vendor: %s", ext);

	ext = (char*)glGetString(GL_RENDERER);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Renderer: %s", ext);

	ext = (char*)glGetString(GL_VERSION);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Version: %s", ext);

	ext = (char*)glGetString(GL_EXTENSIONS);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Extensions: %s", ext);

	if ( strstr(ext, "GL_OES_draw_texture") )
	{
		rc->draw_texture = 1;
		LOG( ANDROID_LOG_INFO, TAG, "Using GL_OES_draw_texture");
	}
	if ( strstr(ext, "GL_ARB_texture_non_power_of_two") )
	{
		rc->non_power_two = 0;
		LOG( ANDROID_LOG_INFO, TAG, "Using GL_ARB_texture_non_power_of_two");
	}

	/* Enable smooth shading */
	glShadeModel(GL_SMOOTH);

	/* Set the background black */
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	/* Depth buffer setup */
	glClearDepthf(1.0f);

	/* Enables Depth Testing */
	glEnable(GL_DEPTH_TEST);

	/* The Type Of Depth Test To Do */
	glDepthFunc(GL_LEQUAL);

	/* Really Nice Perspective Calculations */
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
#endif

void gluPerspective(GLfloat fovy, GLfloat aspect,
                    GLfloat zNear, GLfloat zFar)
{
	GLfloat xmin, xmax, ymin, ymax;

	ymax = zNear * (GLfloat)tan(fovy * PI / 360);
	ymin = -ymax;
	xmin = ymin * aspect;
	xmax = ymax * aspect;
#ifndef GPAC_USE_GLES2
	glFrustumx((GLfixed)(xmin * 65536), (GLfixed)(xmax * 65536),
	           (GLfixed)(ymin * 65536), (GLfixed)(ymax * 65536),
	           (GLfixed)(zNear * 65536), (GLfixed)(zFar * 65536));
#endif
}

void resizeWindow(AndroidContext *rc)
{
	LOG( ANDROID_LOG_VERBOSE, TAG, "resizeWindow : start");
	/* Height / width ration */
	GLfloat ratio;

	/* Protect against a divide by zero */
	if (rc->height==0)
	{
		rc->height=1;
	}

	ratio=(GLfloat)rc->width/(GLfloat)rc->height;

	/* Setup our viewport. */
	glViewport(0, 0, (GLsizei)rc->width, (GLsizei)rc->height);
#ifndef GPAC_USE_GLES2
	/* change to the projection matrix and set our viewing volume. */
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	/* Set our perspective */
	glOrthox(0, INT2FIX(rc->width), 0, INT2FIX(rc->height), INT2FIX(-1), INT2FIX(1));

	/* Make sure we're chaning the model view and not the projection */
	glMatrixMode(GL_MODELVIEW);

	/* Reset The View */
	glLoadIdentity();
#else
	glUseProgram(rc->base_program);
	calculate_ortho(0, INT2FIX(rc->width), 0, INT2FIX(rc->height), INT2FIX(-1), INT2FIX(1), rc);
	load_matrix_shaders(rc->base_program, (Fixed *) rc->ortho.m, "gfProjectionMatrix");
	load_matrix_shaders(rc->base_program, (Fixed *) rc->identity.m, "gfModelViewMatrix");
#endif
	LOG( ANDROID_LOG_VERBOSE, TAG, "resizeWindow : end");
}

void drawGLScene(AndroidContext *rc)
{
#ifdef DROID_EXTREME_LOGS
	LOG( ANDROID_LOG_VERBOSE, TAG, "drawGLScene : start");
#endif /* DROID_EXTREME_LOGS */
#ifdef GPAC_USE_GLES2
	GLuint loc_vertex_array, loc_texcoord_array;
	loc_vertex_array = loc_texcoord_array = -1;
#endif

	GLfloat vertices[4][3];
	GLfloat texcoord[4][2];
//	int i, j;

	float rgba[4];
GL_CHECK_ERR

	// Reset states
	rgba[0] = rgba[1] = rgba[2] = 0.f;
	rgba[0] = 1.f;
#ifndef GPAC_USE_GLES2
	glColor4f(1.f, 1.f, 1.f, 1.f);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, rgba);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, rgba);
	glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, rgba);
#endif
	/* Clear The Screen And The Depth Buffer */
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	GL_CHECK_ERR
	//glEnable(GL_BLEND);
	//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#ifndef GPAC_USE_GLES2
	glEnable(GL_TEXTURE_2D);
#endif
	glUseProgram(rc->base_program);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture( GL_TEXTURE_2D, rc->texID);
	GL_CHECK_ERR
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
#ifndef GPAC_USE_GLES2
	glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
#endif
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

//    for ( i = 0; i < rc->height/2; i++ )
//    	for ( j = 0; j < rc->width; j++ )
//    		rc->texData[ i*rc->width*NBPP + j*NBPP + 3] = 200;

//    memset(rc->texData, 255, 4 * rc->width * rc->height );

	glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, rc->tex_width, rc->tex_height, 0,
	              GL_RGBA, GL_UNSIGNED_BYTE, rc->texData );

GL_CHECK_ERR
	if ( rc->draw_texture )
	{
		GL_CHECK_ERR
		int cropRect[4] = {0,rc->height,rc->width,-rc->height};
#ifndef GPAC_USE_GLES2
		glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
		glDrawTexsOES(0, 0, 0, rc->width, rc->height);
#endif
	}
	else
	{
		GL_CHECK_ERR

#ifndef GPAC_USE_GLES2
		/* Enable VERTEX array */
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		/* Setup pointer to  VERTEX array */
		glVertexPointer(3, GL_FLOAT, 0, vertices);
		glTexCoordPointer(2, GL_FLOAT, 0, texcoord);

		/* Move Left 1.5 Units And Into The Screen 6.0 */
		glLoadIdentity();
#else
		loc_vertex_array = glGetAttribLocation(rc->base_program, "gfVertex");
		if(loc_vertex_array<0)
			return;
		glEnableVertexAttribArray(loc_vertex_array);
		glVertexAttribPointer(loc_vertex_array, 3, GL_FLOAT, GL_FALSE, 0, vertices);

		loc_texcoord_array = glGetAttribLocation(rc->base_program, "gfTexCoord");
		if (loc_texcoord_array>=0) {
			glVertexAttribPointer(loc_texcoord_array, 2, GL_FLOAT, GL_FALSE, 0, texcoord);
			glEnableVertexAttribArray(loc_texcoord_array);
		}


#endif
		//glTranslatef(0.0f, 0.0f, -3.3f);
		//glTranslatef(0.0f, 0.0f, -2.3f);

		/* Top Right Of The Quad    */
		vertices[0][0]=rc->tex_width;
		vertices[0][1]=rc->tex_height;
		vertices[0][2]=0.0f;
		texcoord[0][0]=1.f;
		texcoord[0][1]=0.f;
		/* Top Left Of The Quad     */
		vertices[1][0]=0.f;
		vertices[1][1]=rc->tex_height;
		vertices[1][2]=0.0f;
		texcoord[1][0]=0.f;
		texcoord[1][1]=0.f;
		/* Bottom Left Of The Quad  */
		vertices[2][0]=rc->tex_width;
		vertices[2][1]=0.f;
		vertices[2][2]=0.0f;
		texcoord[2][0]=1.f;
		texcoord[2][1]=1.f;
		/* Bottom Right Of The Quad */
		vertices[3][0]=0.f;
		vertices[3][1]=0.f;
		vertices[3][2]=0.0f;
		texcoord[3][0]=0.f;
		texcoord[3][1]=1.f;

		/* Drawing using triangle strips, draw triangles using 4 vertices */
		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
#ifndef GPAC_USE_GLES2
		/* Disable vertex array */
		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
#endif
	}
#ifndef GPAC_USE_GLES2
	glDisable(GL_TEXTURE_2D);
#endif

	/* Flush all drawings */
	glFinish();
#ifdef DROID_EXTREME_LOGS
	LOG( ANDROID_LOG_VERBOSE, TAG, "drawGLScene : end");
#endif /* DROID_EXTREME_LOGS */
}

int releaseTexture(AndroidContext *rc)
{
	if (!rc)
		return 0;
	LOG( ANDROID_LOG_DEBUG, TAG, "Android Delete Texture");

	if ( rc->texID >= 0 )
	{
		glDeleteTextures(1, &(rc->texID));
		rc->texID = -1;
	}
	if (rc->texData)
	{
		gf_free(rc->texData);
		rc->texData = NULL;
	}
	LOG( ANDROID_LOG_VERBOSE, TAG, "Android Delete Texture DONE");
	return 0;
}

int createTexture(AndroidContext *rc)
{
	if (!rc)
		return 0;
	if ( rc->texID >= 0 )
		releaseTexture(rc);

	LOG( ANDROID_LOG_INFO, TAG, "Android Create Texture Size: WxH: %dx%d",
	     rc->tex_width, rc->tex_height);

	glGenTextures( 1, &(rc->texID) );

	rc->texData = (GLubyte*)gf_malloc( 4 * rc->tex_width * rc->tex_height );
	memset(rc->texData, 255, 4 * rc->tex_width * rc->tex_height );
	//memset(data, 0, 4 * width * height/2 );

	glBindTexture( GL_TEXTURE_2D, rc->texID);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
#ifndef GPAC_USE_GLES2
	glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
#endif
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, rc->tex_width, rc->tex_height, 0,
	              GL_RGBA, GL_UNSIGNED_BYTE, NULL/*rc->texData*/ );

	glBindTexture( GL_TEXTURE_2D, 0);
	LOG( ANDROID_LOG_VERBOSE, TAG, "Android Create Texture DONE");
	return 0;
}


u32 find_pow_2(u32 num)
{
	u32 res = 1;
	while (res < num)
		res *= 2;
	return res;
}

static GF_Err droid_Resize(GF_VideoOutput *dr, u32 w, u32 h)
{
	RAWCTX;
	LOG( ANDROID_LOG_DEBUG, TAG, "Android Resize: %dx%d", w, h);

	rc->width = w;
	rc->height = h;
	
	if ((dr->max_screen_width < w) || (dr->max_screen_height < h)) {
		dr->max_screen_width = w;
		dr->max_screen_height = h;
	}
	//npot textures are supported in ES2
#ifdef GPAC_USE_GLES2
		rc->tex_width = rc->width;
		rc->tex_height = rc->height;
#else
	if ( rc->non_power_two )
	{
		rc->tex_width = rc->width;
		rc->tex_height = rc->height;
	}
	else
	{
		rc->tex_width = find_pow_2(rc->width);
		rc->tex_height = find_pow_2(rc->height);
	}
#endif
GL_CHECK_ERR
	resizeWindow(rc);

	if ( rc->out_3d_type == 0 )
	{
		createTexture(rc);
	}
	LOG( ANDROID_LOG_VERBOSE, TAG, "Android Resize DONE", w, h);
	return GF_OK;
}

GF_Err droid_Setup(GF_VideoOutput *dr, void *os_handle, void *os_display, u32 init_flags)
{
	RAWCTX;
	void * pixels;
	Bool res = GF_FALSE;

	LOG( ANDROID_LOG_DEBUG, TAG, "Android Setup: %d", init_flags);


#ifdef GPAC_USE_GLES2

	if ( rc->out_3d_type == 0 ){
		LOG( ANDROID_LOG_DEBUG, TAG, "We are in OpenGL: disable mode");<commit_msg>added some error checking<commit_after>/*
 *			GPAC - Multimedia Framework C SDK
 *
 *			Authors: <NAME>, <NAME>
 *			Copyright (c) Mines-Telecom 2009-
 *					All rights reserved
 *
 *  This file is part of GPAC / Wrapper
 *
 *  GPAC is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  GPAC is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

/*driver interfaces*/
#include <gpac/modules/video_out.h>
#include <gpac/list.h>
#include <gpac/constants.h>

#include <gpac/setup.h>

#ifdef GPAC_USE_GLES2
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#else
#include <GLES/gl.h>
#include <GLES/glext.h>
#endif

#include <android/log.h>

#ifdef GPAC_USE_GLES2
#define TAG "DROID_VIDEO [GLES2]"
#else
#define TAG "DROID_VIDEO"
#endif

#define LOG   __android_log_print

#ifdef PI
#undef PI
#endif

#define PI 3.1415926535897932f

/* Uncomment the next line if you want to debug */
/* #define DROID_EXTREME_LOGS */

typedef struct
{
	u32 width, height;
	void * locked_data;
	u8 out_3d_type;

	u32 tex_width, tex_height;

	GLuint texID;
	GLuint framebuff;
	GLuint depthbuff;

	GLubyte* texData;

	u8 draw_texture;
	u8 non_power_two;

	Bool fullscreen;

	//Functions specific to OpenGL ES2
	#ifdef GPAC_USE_GLES2
	GLuint base_vertex, base_fragment, base_program;
	GF_Matrix identity, ortho;
	#endif
} AndroidContext;


#define RAW_OUT_PIXEL_FORMAT		GF_PIXEL_RGBA
#define NBPP						4

#define RAWCTX	AndroidContext *rc = (AndroidContext *)dr->opaque



//Functions specific to OpenGL ES2
#ifdef GPAC_USE_GLES2

#define GF_TRUE 1
#define GF_FALSE 0


//we custom-define these instead of importing gl_inc.h
#define GL_COMPILE_STATUS 0x8B81
#define GL_FRAGMENT_SHADER 0x8B30
#define GL_INFO_LOG_LENGTH 0x8B84
#define GL_LINK_STATUS 0x8B82
#define GL_VERTEX_SHADER 0x8B31



static char *glsl_vertex = "precision mediump float;\
	attribute vec4 gfVertex;\
	attribute vec4 gfTexCoord;\
	varying vec2 TexCoord;\
	uniform mat4 gfModelViewMatrix;\
	uniform mat4 gfProjectionMatrix;\
	void main(void){\
		vec4 gfEye;\
		gfEye = gfModelViewMatrix * gfVertex;\
		TexCoord = vec2(gfTexCoord);\
		gl_Position = gfProjectionMatrix * gfEye;\
	}";

static char *glsl_fragment = "precision mediump float;\
	varying vec2 TexCoord;\
	uniform sampler2D img;\
	void main(void){\
		gl_FragColor = texture2D(img, TexCoord);\
	}";

#define GL_CHECK_ERR {s32 res = glGetError(); if (res) GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("GL Error %d file %s line %d\n", res, __FILE__, __LINE__)); }

static GLint gf_glGetUniformLocation(u32 glsl_program, const char *uniform_name)
{
	GLint loc = glGetUniformLocation(glsl_program, uniform_name);
	if (loc<0) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[V3D:GLSL] Cannot find uniform \"%s\" in GLSL program\n", uniform_name));
	}
	return loc;
}

static GLint gf_glGetAttribLocation(u32 glsl_program, const char *attrib_name)
{
	GLint loc = glGetAttribLocation(glsl_program, attrib_name);
	if (loc<0) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[V3D:GLSL] Cannot find attrib \"%s\" in GLSL program\n", attrib_name));
	}
	return loc;
}

//modified version of visual_3d_compile_shader function
Bool compile_shader(u32 shader_id, const char *name, const char *source){
	GLint blen = 0;
	GLsizei slen = 0;
	u32 len;
	GLint is_compiled = 0;


	if(!source || !shader_id) return 0;
	len = (u32) strlen(source);
	glShaderSource(shader_id, 1, &source, &len);
	glCompileShader(shader_id);

	glGetShaderiv(shader_id, GL_COMPILE_STATUS, &is_compiled);
	if (is_compiled == 1) return GF_TRUE;

	glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH , &blen);
	if (blen > 1) {
		char* compiler_log = (char*) gf_malloc(blen);
		glGetShaderInfoLog(shader_id, blen, &slen, compiler_log);
		GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[GLSL] Failed to compile %s shader: %s\n", name, compiler_log));
		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[GLSL] ***** faulty shader code ****\n%s\n**********************\n", source));
		gf_free (compiler_log);
		return GF_FALSE;
	}

	return GF_TRUE;
}


static Bool initGLES2(AndroidContext *rc){


//PRINT OpengGL INFO
	char* ext;

	LOG( ANDROID_LOG_DEBUG, TAG, "Android InitGLES2");

	ext = (char*)glGetString(GL_VENDOR);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Vendor: %s", ext);

	ext = (char*)glGetString(GL_RENDERER);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Renderer: %s", ext);

	ext = (char*)glGetString(GL_VERSION);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Version: %s", ext);

	ext = (char*)glGetString(GL_EXTENSIONS);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Extensions: %s", ext);



//Generic GL setup
	/* Set the background black */
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	/* Depth buffer setup */
	glClearDepthf(1.0f);

	/* Enables Depth Testing */
	glEnable(GL_DEPTH_TEST);

	/* The Type Of Depth Test To Do */
	glDepthFunc(GL_LEQUAL);


//Shaders setup
	Bool res = GF_FALSE;
	GLint linked;

	GL_CHECK_ERR
	gf_mx_init(rc->identity);
	rc->base_program = glCreateProgram();
	rc->base_vertex = glCreateShader(GL_VERTEX_SHADER);
	rc->base_fragment = glCreateShader(GL_FRAGMENT_SHADER);

	LOG( ANDROID_LOG_DEBUG, TAG, ("Compiling shaders"));
	res = compile_shader(rc->base_vertex, "vertex", glsl_vertex);
	if(!res) return GF_FALSE;
	res = compile_shader(rc->base_fragment, "fragment", glsl_fragment);
	if(!res) return GF_FALSE;

	glAttachShader(rc->base_program, rc->base_vertex);
	glAttachShader(rc->base_program, rc->base_fragment);
	glLinkProgram(rc->base_program);

	glGetProgramiv(rc->base_program, GL_LINK_STATUS, &linked);
	if (!linked) {
		int i32CharsWritten, i32InfoLogLength;
		char pszInfoLog[2048];
		glGetProgramiv(rc->base_program, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
		glGetProgramInfoLog(rc->base_program, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
		GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, (pszInfoLog));
		return GF_FALSE;
	}
	glUseProgram(rc->base_program);
	GL_CHECK_ERR
	LOG( ANDROID_LOG_DEBUG, TAG, "Shaders compiled");

	return GF_TRUE;
}

static void load_matrix_shaders(GLuint program, Fixed *mat, const char *name)
{
	GLint loc=-1;
#ifdef GPAC_FIXED_POINT
	Float _mat[16];
	u32 i;
#endif
GL_CHECK_ERR
	loc = glGetUniformLocation(program, name);
	if(loc<0){
		GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("GL Error (file %s line %d): Invalid matrix name", __FILE__, __LINE__));
		return;
	}
	GL_CHECK_ERR

#ifdef GPAC_FIXED_POINT
	for (i=0; i<16;i++) _mat[i] = FIX2FLT(mat[i]);
	glUniformMatrix4fv(loc, 1, GL_FALSE, (GLfloat *) _mat);
#else
	glUniformMatrix4fv(loc, 1, GL_FALSE, mat);
#endif
	GL_CHECK_ERR
}


//ES2 version of glOrthox() - resulting matrix is stored in rc->ortho
//more info on Orthographic projection matrix at http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho
static void calculate_ortho(Fixed left, Fixed right, Fixed bottom, Fixed top, Fixed near, Fixed far,  AndroidContext *rc){


	if((left==right)|(bottom==top)|(near==far)){
		GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("GL Error (file %s line %d): Invalid Orthogonal projection values", __FILE__, __LINE__));
		return;
	}

	gf_mx_init(rc->ortho);

//For Orthographic Projection
	rc->ortho.m[0] = gf_divfix(2, (right-left));
	rc->ortho.m[5] = gf_divfix(2, (top-bottom));
	rc->ortho.m[10] = gf_divfix(-2, far-near);
	rc->ortho.m[12] = -gf_divfix(right+left, right-left);
	rc->ortho.m[13] = -gf_divfix(top+bottom, top-bottom);
	rc->ortho.m[14] = -gf_divfix(far+near, far-near);
	rc->ortho.m[15] = FIX_ONE;
}



#endif	//Endof specifix for GLES2 (ifdef GPAC_USE_GLES2)


#ifndef GPAC_USE_GLES2
void initGL(AndroidContext *rc)
{
	char* ext;

	LOG( ANDROID_LOG_DEBUG, TAG, "Android InitGL");

	ext = (char*)glGetString(GL_VENDOR);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Vendor: %s", ext);

	ext = (char*)glGetString(GL_RENDERER);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Renderer: %s", ext);

	ext = (char*)glGetString(GL_VERSION);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Version: %s", ext);

	ext = (char*)glGetString(GL_EXTENSIONS);
	LOG( ANDROID_LOG_INFO, TAG, "OpenGL ES Extensions: %s", ext);

	if ( strstr(ext, "GL_OES_draw_texture") )
	{
		rc->draw_texture = 1;
		LOG( ANDROID_LOG_INFO, TAG, "Using GL_OES_draw_texture");
	}
	if ( strstr(ext, "GL_ARB_texture_non_power_of_two") )
	{
		rc->non_power_two = 0;
		LOG( ANDROID_LOG_INFO, TAG, "Using GL_ARB_texture_non_power_of_two");
	}

	/* Enable smooth shading */
	glShadeModel(GL_SMOOTH);

	/* Set the background black */
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	/* Depth buffer setup */
	glClearDepthf(1.0f);

	/* Enables Depth Testing */
	glEnable(GL_DEPTH_TEST);

	/* The Type Of Depth Test To Do */
	glDepthFunc(GL_LEQUAL);

	/* Really Nice Perspective Calculations */
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
#endif

void gluPerspective(GLfloat fovy, GLfloat aspect,
                    GLfloat zNear, GLfloat zFar)
{
	GLfloat xmin, xmax, ymin, ymax;

	ymax = zNear * (GLfloat)tan(fovy * PI / 360);
	ymin = -ymax;
	xmin = ymin * aspect;
	xmax = ymax * aspect;
#ifndef GPAC_USE_GLES2
	glFrustumx((GLfixed)(xmin * 65536), (GLfixed)(xmax * 65536),
	           (GLfixed)(ymin * 65536), (GLfixed)(ymax * 65536),
	           (GLfixed)(zNear * 65536), (GLfixed)(zFar * 65536));
#endif
}

void resizeWindow(AndroidContext *rc)
{
	LOG( ANDROID_LOG_VERBOSE, TAG, "resizeWindow : start");
	/* Height / width ration */
	GLfloat ratio;

	/* Protect against a divide by zero */
	if (rc->height==0)
	{
		rc->height=1;
	}

	ratio=(GLfloat)rc->width/(GLfloat)rc->height;

	/* Setup our viewport. */
	glViewport(0, 0, (GLsizei)rc->width, (GLsizei)rc->height);
#ifndef GPAC_USE_GLES2
	/* change to the projection matrix and set our viewing volume. */
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	/* Set our perspective */
	glOrthox(0, INT2FIX(rc->width), 0, INT2FIX(rc->height), INT2FIX(-1), INT2FIX(1));

	/* Make sure we're chaning the model view and not the projection */
	glMatrixMode(GL_MODELVIEW);

	/* Reset The View */
	glLoadIdentity();
#else
	GL_CHECK_ERR
	glUseProgram(rc->base_program);
	calculate_ortho(0, INT2FIX(rc->width), 0, INT2FIX(rc->height), INT2FIX(-1), INT2FIX(1), rc);
	load_matrix_shaders(rc->base_program, (Fixed *) rc->ortho.m, "gfProjectionMatrix");
	load_matrix_shaders(rc->base_program, (Fixed *) rc->identity.m, "gfModelViewMatrix");
	GL_CHECK_ERR
#endif
	LOG( ANDROID_LOG_VERBOSE, TAG, "resizeWindow : end");
}

void drawGLScene(AndroidContext *rc)
{
#ifdef DROID_EXTREME_LOGS
	LOG( ANDROID_LOG_VERBOSE, TAG, "drawGLScene : start");
#endif /* DROID_EXTREME_LOGS */
#ifdef GPAC_USE_GLES2
	GLuint loc_vertex_array, loc_texcoord_array;
	loc_vertex_array = loc_texcoord_array = -1;
#endif

	GLfloat vertices[4][3];
	GLfloat texcoord[4][2];
//	int i, j;

	float rgba[4];
GL_CHECK_ERR

	// Reset states
	rgba[0] = rgba[1] = rgba[2] = 0.f;
	rgba[0] = 1.f;
#ifndef GPAC_USE_GLES2
	glColor4f(1.f, 1.f, 1.f, 1.f);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, rgba);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, rgba);
	glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, rgba);
#endif
	/* Clear The Screen And The Depth Buffer */
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	GL_CHECK_ERR
	//glEnable(GL_BLEND);
	//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#ifndef GPAC_USE_GLES2
	glEnable(GL_TEXTURE_2D);
#endif
	glUseProgram(rc->base_program);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture( GL_TEXTURE_2D, rc->texID);
	GL_CHECK_ERR
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
#ifndef GPAC_USE_GLES2
	glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
#endif
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

//    for ( i = 0; i < rc->height/2; i++ )
//    	for ( j = 0; j < rc->width; j++ )
//    		rc->texData[ i*rc->width*NBPP + j*NBPP + 3] = 200;

//    memset(rc->texData, 255, 4 * rc->width * rc->height );

	glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, rc->tex_width, rc->tex_height, 0,
	              GL_RGBA, GL_UNSIGNED_BYTE, rc->texData );

GL_CHECK_ERR
	if ( rc->draw_texture )
	{
		GL_CHECK_ERR
		int cropRect[4] = {0,rc->height,rc->width,-rc->height};
#ifndef GPAC_USE_GLES2
		glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
		glDrawTexsOES(0, 0, 0, rc->width, rc->height);
#endif
	}
	else
	{
		GL_CHECK_ERR

#ifndef GPAC_USE_GLES2
		/* Enable VERTEX array */
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		/* Setup pointer to  VERTEX array */
		glVertexPointer(3, GL_FLOAT, 0, vertices);
		glTexCoordPointer(2, GL_FLOAT, 0, texcoord);

		/* Move Left 1.5 Units And Into The Screen 6.0 */
		glLoadIdentity();
#else
		loc_vertex_array = glGetAttribLocation(rc->base_program, "gfVertex");
		if(loc_vertex_array<0)
			return;
		glEnableVertexAttribArray(loc_vertex_array);
		glVertexAttribPointer(loc_vertex_array, 3, GL_FLOAT, GL_FALSE, 0, vertices);

		loc_texcoord_array = glGetAttribLocation(rc->base_program, "gfTexCoord");
		if (loc_texcoord_array>=0) {
			glVertexAttribPointer(loc_texcoord_array, 2, GL_FLOAT, GL_FALSE, 0, texcoord);
			glEnableVertexAttribArray(loc_texcoord_array);
		}


#endif
		//glTranslatef(0.0f, 0.0f, -3.3f);
		//glTranslatef(0.0f, 0.0f, -2.3f);

		/* Top Right Of The Quad    */
		vertices[0][0]=rc->tex_width;
		vertices[0][1]=rc->tex_height;
		vertices[0][2]=0.0f;
		texcoord[0][0]=1.f;
		texcoord[0][1]=0.f;
		/* Top Left Of The Quad     */
		vertices[1][0]=0.f;
		vertices[1][1]=rc->tex_height;
		vertices[1][2]=0.0f;
		texcoord[1][0]=0.f;
		texcoord[1][1]=0.f;
		/* Bottom Left Of The Quad  */
		vertices[2][0]=rc->tex_width;
		vertices[2][1]=0.f;
		vertices[2][2]=0.0f;
		texcoord[2][0]=1.f;
		texcoord[2][1]=1.f;
		/* Bottom Right Of The Quad */
		vertices[3][0]=0.f;
		vertices[3][1]=0.f;
		vertices[3][2]=0.0f;
		texcoord[3][0]=0.f;
		texcoord[3][1]=1.f;

		/* Drawing using triangle strips, draw triangles using 4 vertices */
		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
#ifndef GPAC_USE_GLES2
		/* Disable vertex array */
		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
#endif
	}
#ifndef GPAC_USE_GLES2
	glDisable(GL_TEXTURE_2D);
#endif
	GL_CHECK_ERR

	/* Flush all drawings */
	glFinish();
#ifdef DROID_EXTREME_LOGS
	LOG( ANDROID_LOG_VERBOSE, TAG, "drawGLScene : end");
#endif /* DROID_EXTREME_LOGS */
}

int releaseTexture(AndroidContext *rc)
{
	GL_CHECK_ERR
	if (!rc)
		return 0;
	LOG( ANDROID_LOG_DEBUG, TAG, "Android Delete Texture");

	if ( rc->texID >= 0 )
	{
		glDeleteTextures(1, &(rc->texID));
		rc->texID = -1;
	}
	if (rc->texData)
	{
		gf_free(rc->texData);
		rc->texData = NULL;
	}
	LOG( ANDROID_LOG_VERBOSE, TAG, "Android Delete Texture DONE");
	GL_CHECK_ERR
	return 0;
}

int createTexture(AndroidContext *rc)
{
	if (!rc)
		return 0;
	if ( rc->texID >= 0 )
		releaseTexture(rc);

	LOG( ANDROID_LOG_INFO, TAG, "Android Create Texture Size: WxH: %dx%d",
	     rc->tex_width, rc->tex_height);

	glGenTextures( 1, &(rc->texID) );

	rc->texData = (GLubyte*)gf_malloc( 4 * rc->tex_width * rc->tex_height );
	memset(rc->texData, 255, 4 * rc->tex_width * rc->tex_height );
	//memset(data, 0, 4 * width * height/2 );

	glBindTexture( GL_TEXTURE_2D, rc->texID);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
#ifndef GPAC_USE_GLES2
	glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
#endif
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, rc->tex_width, rc->tex_height, 0,
	              GL_RGBA, GL_UNSIGNED_BYTE, NULL/*rc->texData*/ );

	glBindTexture( GL_TEXTURE_2D, 0);
	LOG( ANDROID_LOG_VERBOSE, TAG, "Android Create Texture DONE");
	return 0;
}


u32 find_pow_2(u32 num)
{
	u32 res = 1;
	while (res < num)
		res *= 2;
	return res;
}

static GF_Err droid_Resize(GF_VideoOutput *dr, u32 w, u32 h)
{
	RAWCTX;
	LOG( ANDROID_LOG_DEBUG, TAG, "Android Resize: %dx%d", w, h);

	rc->width = w;
	rc->height = h;
	
	if ((dr->max_screen_width < w) || (dr->max_screen_height < h)) {
		dr->max_screen_width = w;
		dr->max_screen_height = h;
	}
	//npot textures are supported in ES2
#ifdef GPAC_USE_GLES2
		rc->tex_width = rc->width;
		rc->tex_height = rc->height;
#else
	if ( rc->non_power_two )
	{
		rc->tex_width = rc->width;
		rc->tex_height = rc->height;
	}
	else
	{
		rc->tex_width = find_pow_2(rc->width);
		rc->tex_height = find_pow_2(rc->height);
	}
#endif
GL_CHECK_ERR
	resizeWindow(rc);

	if ( rc->out_3d_type == 0 )
	{
		createTexture(rc);
	}
	LOG( ANDROID_LOG_VERBOSE, TAG, "Android Resize DONE", w, h);
	GL_CHECK_ERR
	return GF_OK;
}

GF_Err droid_Setup(GF_VideoOutput *dr, void *os_handle, void *os_display, u32 init_flags)
{
	RAWCTX;
	void * pixels;
	Bool res = GF_FALSE;

	LOG( ANDROID_LOG_DEBUG, TAG, "Android Setup: %d", init_flags);


#ifdef GPAC_USE_GLES2

	if ( rc->out_3d_type == 0 ){
		LOG( ANDROID_LOG_DEBUG, TAG, "We are in OpenGL: disable mode");
{'fraction_non_alphanumeric': 0.13706453455168474, 'fraction_numerical': 0.02444317532838378, 'mean_word_length': 4.897777029302795, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 247, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4901938', 'n_tokens_mistral': 15160, 'n_tokens_neox': 14119, 'n_words': 3076}