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