testegl: convert code from GLESv1 to GLESv2

See https://bugzilla.gnome.org/show_bug.cgi?id=728940
This commit is contained in:
Julien Isorce 2014-04-25 17:32:16 +01:00
parent f1c76ef921
commit 31cd1fd77b
3 changed files with 413 additions and 157 deletions

View file

@ -13,7 +13,8 @@ testegl_LDADD = \
-lgstvideo-@GST_API_VERSION@ \
$(GST_BASE_LIBS) \
$(GST_LIBS) \
$(GST_GL_LIBS)
$(GST_GL_LIBS) \
-lm
testegl_CFLAGS = \
$(GST_PLUGINS_BASE_CFLAGS) \

View file

@ -27,42 +27,42 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Spatial coordinates for the cube
static const GLbyte quadx[6*4*3] = {
static const GLfloat quadx[6*4*3] = {
/* FRONT */
-10, -10, 10,
10, -10, 10,
-10, 10, 10,
10, 10, 10,
-1.f, -1.f, 1.f,
1.f, -1.f, 1.f,
-1.f, 1.f, 1.f,
1.f, 1.f, 1.f,
/* BACK */
-10, -10, -10,
-10, 10, -10,
10, -10, -10,
10, 10, -10,
-1.f, -1.f, -1.f,
-1.f, 1.f, -1.f,
1.f, -1.f, -1.f,
1.f, 1.f, -1.f,
/* LEFT */
-10, -10, 10,
-10, 10, 10,
-10, -10, -10,
-10, 10, -10,
-1.f, -1.f, 1.f,
-1.f, 1.f, 1.f,
-1.f, -1.f, -1.f,
-1.f, 1.f, -1.f,
/* RIGHT */
10, -10, -10,
10, 10, -10,
10, -10, 10,
10, 10, 10,
1.f, -1.f, -1.f,
1.f, 1.f, -1.f,
1.f, -1.f, 1.f,
1.f, 1.f, 1.f,
/* TOP */
-10, 10, 10,
10, 10, 10,
-10, 10, -10,
10, 10, -10,
-1.f, 1.f, 1.f,
1.f, 1.f, 1.f,
-1.f, 1.f, -1.f,
1.f, 1.f, -1.f,
/* BOTTOM */
-10, -10, 10,
-10, -10, -10,
10, -10, 10,
10, -10, -10,
-1.f, -1.f, 1.f,
-1.f, -1.f, -1.f,
1.f, -1.f, 1.f,
1.f, -1.f, -1.f,
};
/** Texture coordinates for the quad. */

View file

@ -57,9 +57,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma GCC optimize ("gnu89-inline")
#endif
#include <GLES/gl.h>
#include <GLES/glext.h>
#include <gst/gl/gl.h>
#include <gst/gl/egl/gstgldisplay_egl.h>
@ -122,6 +119,187 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define TRACE_VC_MEMORY_ONCE(str,id) while(0)
#endif
/* some helpers that we should provide in libgstgl */
typedef struct
{
GLfloat m[4][4];
} GstGLMatrix;
static void
gst_gl_matrix_load_identity (GstGLMatrix * matrix)
{
memset (matrix, 0x0, sizeof (GstGLMatrix));
matrix->m[0][0] = 1.0f;
matrix->m[1][1] = 1.0f;
matrix->m[2][2] = 1.0f;
matrix->m[3][3] = 1.0f;
}
static void
gst_gl_matrix_multiply (GstGLMatrix * matrix, GstGLMatrix * srcA,
GstGLMatrix * srcB)
{
GstGLMatrix tmp;
int i;
for (i = 0; i < 4; i++) {
tmp.m[i][0] = (srcA->m[i][0] * srcB->m[0][0]) +
(srcA->m[i][1] * srcB->m[1][0]) +
(srcA->m[i][2] * srcB->m[2][0]) + (srcA->m[i][3] * srcB->m[3][0]);
tmp.m[i][1] = (srcA->m[i][0] * srcB->m[0][1]) +
(srcA->m[i][1] * srcB->m[1][1]) +
(srcA->m[i][2] * srcB->m[2][1]) + (srcA->m[i][3] * srcB->m[3][1]);
tmp.m[i][2] = (srcA->m[i][0] * srcB->m[0][2]) +
(srcA->m[i][1] * srcB->m[1][2]) +
(srcA->m[i][2] * srcB->m[2][2]) + (srcA->m[i][3] * srcB->m[3][2]);
tmp.m[i][3] = (srcA->m[i][0] * srcB->m[0][3]) +
(srcA->m[i][1] * srcB->m[1][3]) +
(srcA->m[i][2] * srcB->m[2][3]) + (srcA->m[i][3] * srcB->m[3][3]);
}
memcpy (matrix, &tmp, sizeof (GstGLMatrix));
}
static void
gst_gl_matrix_translate (GstGLMatrix * matrix, GLfloat tx, GLfloat ty,
GLfloat tz)
{
matrix->m[3][0] +=
(matrix->m[0][0] * tx + matrix->m[1][0] * ty + matrix->m[2][0] * tz);
matrix->m[3][1] +=
(matrix->m[0][1] * tx + matrix->m[1][1] * ty + matrix->m[2][1] * tz);
matrix->m[3][2] +=
(matrix->m[0][2] * tx + matrix->m[1][2] * ty + matrix->m[2][2] * tz);
matrix->m[3][3] +=
(matrix->m[0][3] * tx + matrix->m[1][3] * ty + matrix->m[2][3] * tz);
}
static void
gst_gl_matrix_rotate (GstGLMatrix * matrix, GLfloat angle, GLfloat x, GLfloat y,
GLfloat z)
{
GLfloat sinAngle, cosAngle;
GLfloat mag = sqrtf (x * x + y * y + z * z);
sinAngle = sinf (angle * M_PI / 180.0f);
cosAngle = cosf (angle * M_PI / 180.0f);
if (mag > 0.0f) {
GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs;
GLfloat oneMinusCos;
GstGLMatrix rotMat;
x /= mag;
y /= mag;
z /= mag;
xx = x * x;
yy = y * y;
zz = z * z;
xy = x * y;
yz = y * z;
zx = z * x;
xs = x * sinAngle;
ys = y * sinAngle;
zs = z * sinAngle;
oneMinusCos = 1.0f - cosAngle;
rotMat.m[0][0] = (oneMinusCos * xx) + cosAngle;
rotMat.m[0][1] = (oneMinusCos * xy) - zs;
rotMat.m[0][2] = (oneMinusCos * zx) + ys;
rotMat.m[0][3] = 0.0f;
rotMat.m[1][0] = (oneMinusCos * xy) + zs;
rotMat.m[1][1] = (oneMinusCos * yy) + cosAngle;
rotMat.m[1][2] = (oneMinusCos * yz) - xs;
rotMat.m[1][3] = 0.0f;
rotMat.m[2][0] = (oneMinusCos * zx) - ys;
rotMat.m[2][1] = (oneMinusCos * yz) + xs;
rotMat.m[2][2] = (oneMinusCos * zz) + cosAngle;
rotMat.m[2][3] = 0.0f;
rotMat.m[3][0] = 0.0f;
rotMat.m[3][1] = 0.0f;
rotMat.m[3][2] = 0.0f;
rotMat.m[3][3] = 1.0f;
gst_gl_matrix_multiply (matrix, &rotMat, matrix);
}
}
static void
gst_gl_matrix_frustum (GstGLMatrix * matrix, GLfloat left, GLfloat right,
GLfloat bottom, GLfloat top, GLfloat nearZ, GLfloat farZ)
{
GLfloat deltaX = right - left;
GLfloat deltaY = top - bottom;
GLfloat deltaZ = farZ - nearZ;
GstGLMatrix frust;
if ((nearZ <= 0.0f) || (farZ <= 0.0f) ||
(deltaX <= 0.0f) || (deltaY <= 0.0f) || (deltaZ <= 0.0f))
return;
frust.m[0][0] = 2.0f * nearZ / deltaX;
frust.m[0][1] = frust.m[0][2] = frust.m[0][3] = 0.0f;
frust.m[1][1] = 2.0f * nearZ / deltaY;
frust.m[1][0] = frust.m[1][2] = frust.m[1][3] = 0.0f;
frust.m[2][0] = (right + left) / deltaX;
frust.m[2][1] = (top + bottom) / deltaY;
frust.m[2][2] = -(nearZ + farZ) / deltaZ;
frust.m[2][3] = -1.0f;
frust.m[3][2] = -2.0f * nearZ * farZ / deltaZ;
frust.m[3][0] = frust.m[3][1] = frust.m[3][3] = 0.0f;
gst_gl_matrix_multiply (matrix, &frust, matrix);
}
static void
gst_gl_matrix_perspective (GstGLMatrix * matrix, GLfloat fovy, GLfloat aspect,
GLfloat nearZ, GLfloat farZ)
{
GLfloat frustumW, frustumH;
frustumH = tanf (fovy / 360.0f * M_PI) * nearZ;
frustumW = frustumH * aspect;
gst_gl_matrix_frustum (matrix, -frustumW, frustumW, -frustumH, frustumH,
nearZ, farZ);
}
/* *INDENT-OFF* */
/* vertex source */
static const gchar *cube_v_src =
"attribute vec4 a_position; \n"
"attribute vec2 a_texCoord; \n"
"uniform mat4 u_matrix; \n"
"varying vec2 v_texCoord; \n"
"void main() \n"
"{ \n"
" gl_Position = u_matrix * a_position; \n"
" v_texCoord = a_texCoord; \n"
"} \n";
/* fragment source */
static const gchar *cube_f_src =
"precision mediump float; \n"
"varying vec2 v_texCoord; \n"
"uniform sampler2D s_texture; \n"
"void main() \n"
"{ \n"
" gl_FragColor = texture2D (s_texture, v_texCoord); \n"
"} \n";
/* *INDENT-ON* */
typedef struct
{
#if defined (USE_OMX_TARGET_RPI)
@ -133,12 +311,26 @@ typedef struct
uint32_t screen_height;
gboolean animate;
GstCaps *caps;
/* OpenGL|ES objects */
EGLDisplay display;
EGLSurface surface;
EGLContext context;
GLuint tex;
GLint vshader;
GLint fshader;
GLint program;
GLint u_modelviewprojectionmatrix;
GLint s_texture;
GstGLMatrix modelview;
GstGLMatrix projection;
GLfloat fov;
GLfloat aspect;
/* model rotation vector and direction */
GLfloat rot_angle_x_inc;
GLfloat rot_angle_y_inc;
@ -157,6 +349,7 @@ typedef struct
GstElement *pipeline;
GstElement *vsink;
GstGLDisplayEGL *gst_display;
gboolean can_avoid_upload;
/* Interthread comunication */
GAsyncQueue *queue;
@ -170,8 +363,6 @@ typedef struct
GMainLoop *main_loop;
GstBuffer *last_buffer;
GstCaps *current_caps;
/* Rendering thread state */
gboolean running;
@ -184,10 +375,9 @@ static void init_ogl (APP_STATE_T * state);
static void init_model_proj (APP_STATE_T * state);
static void reset_model (APP_STATE_T * state);
static GLfloat inc_and_wrap_angle (GLfloat angle, GLfloat angle_inc);
static GLfloat inc_and_clip_distance (GLfloat distance, GLfloat distance_inc);
static void redraw_scene (APP_STATE_T * state);
static void update_model (APP_STATE_T * state);
static void init_textures (APP_STATE_T * state);
static void init_textures (APP_STATE_T * state, GstBuffer * buffer);
static APP_STATE_T _state, *state = &_state;
static gboolean queue_object (APP_STATE_T * state, GstMiniObject * obj,
gboolean synchronous);
@ -236,17 +426,19 @@ init_ogl (APP_STATE_T * state)
DISPMANX_UPDATE_HANDLE_T dispman_update;
VC_RECT_T dst_rect;
VC_RECT_T src_rect;
VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS, 255, 0 };
#endif
//FIXME
static const EGLint attribute_list[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 16,
//EGL_SAMPLES, 4,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
static const EGLint context_attributes[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
@ -275,7 +467,8 @@ init_ogl (APP_STATE_T * state)
/* create an EGL rendering context */
state->context =
eglCreateContext (state->display, config, EGL_NO_CONTEXT, NULL);
eglCreateContext (state->display, config, EGL_NO_CONTEXT,
context_attributes);
assert (state->context != EGL_NO_CONTEXT);
#if defined (USE_OMX_TARGET_RPI)
@ -300,7 +493,7 @@ init_ogl (APP_STATE_T * state)
state->dispman_element =
vc_dispmanx_element_add (dispman_update, state->dispman_display,
0 /*layer */ , &dst_rect, 0 /*src */ ,
&src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha */ , 0 /*clamp */ ,
&src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0 /*clamp */ ,
0 /*transform */ );
nativewindow.element = state->dispman_element;
@ -320,14 +513,6 @@ init_ogl (APP_STATE_T * state)
eglMakeCurrent (state->display, state->surface, state->surface,
state->context);
assert (EGL_FALSE != result);
/* Set background color and clear buffers */
glClearColor (0.15f, 0.25f, 0.35f, 1.0f);
/* Enable back face culling. */
glEnable (GL_CULL_FACE);
glMatrixMode (GL_MODELVIEW);
}
/***********************************************************
@ -344,26 +529,54 @@ init_ogl (APP_STATE_T * state)
static void
init_model_proj (APP_STATE_T * state)
{
float nearp = 1.0f;
float farp = 500.0f;
float hht;
float hwd;
GLint ret = 0;
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
state->vshader = glCreateShader (GL_VERTEX_SHADER);
glShaderSource (state->vshader, 1, &cube_v_src, NULL);
glCompileShader (state->vshader);
assert (glGetError () == GL_NO_ERROR);
state->fshader = glCreateShader (GL_FRAGMENT_SHADER);
glShaderSource (state->fshader, 1, &cube_f_src, NULL);
glCompileShader (state->fshader);
assert (glGetError () == GL_NO_ERROR);
state->program = glCreateProgram ();
glAttachShader (state->program, state->vshader);
glAttachShader (state->program, state->fshader);
glBindAttribLocation (state->program, 0, "a_position");
glBindAttribLocation (state->program, 1, "a_texCoord");
glLinkProgram (state->program);
glGetProgramiv (state->program, GL_LINK_STATUS, &ret);
assert (ret == GL_TRUE);
glUseProgram (state->program);
state->u_modelviewprojectionmatrix =
glGetUniformLocation (state->program, "u_matrix");
state->s_texture = glGetUniformLocation (state->program, "s_texture");
glViewport (0, 0, (GLsizei) state->screen_width,
(GLsizei) state->screen_height);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
state->fov = 45.0f;
state->distance = 5.0f;
state->aspect =
(GLfloat) state->screen_width / (GLfloat) state->screen_height;
hht = nearp * (float) tan (45.0 / 2.0 / 180.0 * M_PI);
hwd = hht * (float) state->screen_width / (float) state->screen_height;
gst_gl_matrix_load_identity (&state->projection);
gst_gl_matrix_perspective (&state->projection, state->fov, state->aspect,
1.0f, 100.0f);
glFrustumf (-hwd, hwd, -hht, hht, nearp, farp);
glEnableClientState (GL_VERTEX_ARRAY);
glVertexPointer (3, GL_BYTE, 0, quadx);
gst_gl_matrix_load_identity (&state->modelview);
gst_gl_matrix_translate (&state->modelview, 0.0f, 0.0f, -state->distance);
reset_model (state);
}
@ -382,11 +595,6 @@ init_model_proj (APP_STATE_T * state)
static void
reset_model (APP_STATE_T * state)
{
/* reset model position */
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glTranslatef (0.f, 0.f, -50.f);
/* reset model rotation */
state->rot_angle_x = 45.f;
state->rot_angle_y = 30.f;
@ -394,7 +602,6 @@ reset_model (APP_STATE_T * state)
state->rot_angle_x_inc = 0.5f;
state->rot_angle_y_inc = 0.5f;
state->rot_angle_z_inc = 0.f;
state->distance = 40.f;
}
/***********************************************************
@ -419,18 +626,7 @@ update_model (APP_STATE_T * state)
inc_and_wrap_angle (state->rot_angle_y, state->rot_angle_y_inc);
state->rot_angle_z =
inc_and_wrap_angle (state->rot_angle_z, state->rot_angle_z_inc);
state->distance =
inc_and_clip_distance (state->distance, state->distance_inc);
}
glLoadIdentity ();
/* move camera back to see the cube */
glTranslatef (0.f, 0.f, -state->distance);
/* Rotate model to new position */
glRotatef (state->rot_angle_x, 1.f, 0.f, 0.f);
glRotatef (state->rot_angle_y, 0.f, 1.f, 0.f);
glRotatef (state->rot_angle_z, 0.f, 0.f, 1.f);
}
/***********************************************************
@ -459,32 +655,6 @@ inc_and_wrap_angle (GLfloat angle, GLfloat angle_inc)
return angle;
}
/***********************************************************
* Name: inc_and_clip_distance
*
* Arguments:
* GLfloat distance current distance
* GLfloat distance_inc distance increment
*
* Description: Increments or decrements distance by distance_inc units
* Clips to range
*
* Returns: new value of angle
*
***********************************************************/
static GLfloat
inc_and_clip_distance (GLfloat distance, GLfloat distance_inc)
{
distance += distance_inc;
if (distance >= 120.0f)
distance = 120.f;
else if (distance <= 40.0f)
distance = 40.0f;
return distance;
}
/***********************************************************
* Name: redraw_scene
*
@ -500,32 +670,53 @@ inc_and_clip_distance (GLfloat distance, GLfloat distance_inc)
static void
redraw_scene (APP_STATE_T * state)
{
/* Start with a clear screen */
GstGLMatrix modelview;
GstGLMatrix modelviewprojection;
glBindFramebuffer (GL_FRAMEBUFFER, 0);
glEnable (GL_CULL_FACE);
glEnable (GL_DEPTH_TEST);
/* Set background color and clear buffers */
glClearColor (0.15f, 0.25f, 0.35f, 1.0f);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* Need to rotate textures - do this by rotating each cube face */
glRotatef (270.f, 0.f, 0.f, 1.f); /* front face normal along z axis */
glUseProgram (state->program);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, quadx);
glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
glEnableVertexAttribArray (0);
glEnableVertexAttribArray (1);
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, state->tex);
glUniform1i (state->s_texture, 0);
memcpy (&modelview, &state->modelview, sizeof (GstGLMatrix));
gst_gl_matrix_rotate (&modelview, state->rot_angle_x, 1.0f, 0.0f, 0.0f);
gst_gl_matrix_rotate (&modelview, state->rot_angle_y, 0.0f, 1.0f, 0.0f);
gst_gl_matrix_rotate (&modelview, state->rot_angle_z, 0.0f, 0.0f, 1.0f);
gst_gl_matrix_load_identity (&modelviewprojection);
gst_gl_matrix_multiply (&modelviewprojection, &modelview, &state->projection);
glUniformMatrix4fv (state->u_modelviewprojectionmatrix, 1, GL_FALSE,
&modelviewprojection.m[0][0]);
/* draw first 4 vertices */
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
/* same pattern for other 5 faces - rotation chosen to make image orientation 'nice' */
glRotatef (90.f, 0.f, 0.f, 1.f); /* back face normal along z axis */
glDrawArrays (GL_TRIANGLE_STRIP, 4, 4);
glRotatef (90.f, 1.f, 0.f, 0.f); /* left face normal along x axis */
glDrawArrays (GL_TRIANGLE_STRIP, 8, 4);
glRotatef (90.f, 1.f, 0.f, 0.f); /* right face normal along x axis */
glDrawArrays (GL_TRIANGLE_STRIP, 12, 4);
glRotatef (270.f, 0.f, 1.f, 0.f); /* top face normal along y axis */
glDrawArrays (GL_TRIANGLE_STRIP, 16, 4);
glRotatef (90.f, 0.f, 1.f, 0.f); /* bottom face normal along y axis */
glDrawArrays (GL_TRIANGLE_STRIP, 20, 4);
eglSwapBuffers (state->display, state->surface);
glDisable (GL_DEPTH_TEST);
glDisable (GL_CULL_FACE);
}
/***********************************************************
@ -541,11 +732,33 @@ redraw_scene (APP_STATE_T * state)
*
***********************************************************/
static void
init_textures (APP_STATE_T * state)
init_textures (APP_STATE_T * state, GstBuffer * buffer)
{
glGenTextures (1, &state->tex);
GstCapsFeatures *feature = gst_caps_get_features (state->caps, 0);
glBindTexture (GL_TEXTURE_2D, state->tex);
if (gst_caps_features_contains (feature, "memory:EGLImage")) {
/* nothing special to do */
g_print ("Prepare texture for EGLImage\n");
state->can_avoid_upload = FALSE;
glGenTextures (1, &state->tex);
glBindTexture (GL_TEXTURE_2D, state->tex);
} else if (gst_caps_features_contains (feature, "memory:GLMemory")) {
g_print ("Prepare texture for GLMemory\n");
state->can_avoid_upload = TRUE;
state->tex = 0;
} else if (gst_caps_features_contains (feature,
"meta:GstVideoGLTextureUploadMeta")) {
GstVideoMeta *meta = NULL;
g_print ("Prepare texture for GstVideoGLTextureUploadMeta\n");
meta = gst_buffer_get_video_meta (buffer);
state->can_avoid_upload = FALSE;
glGenTextures (1, &state->tex);
glBindTexture (GL_TEXTURE_2D, state->tex);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, meta->width, meta->height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
} else {
g_assert_not_reached ();
}
#if 0
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@ -558,14 +771,7 @@ init_textures (APP_STATE_T * state)
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
/* setup overall texture environment */
glTexCoordPointer (2, GL_FLOAT, 0, texCoords);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
glEnable (GL_TEXTURE_2D);
/* Bind texture surface to current vertices */
glBindTexture (GL_TEXTURE_2D, state->tex);
assert (glGetError () == GL_NO_ERROR);
}
static void
@ -574,8 +780,6 @@ render_scene (APP_STATE_T * state)
update_model (state);
redraw_scene (state);
TRACE_VC_MEMORY_ONCE_FOR_ID ("after render_scene", gid2);
return;
}
static void
@ -583,13 +787,30 @@ update_image (APP_STATE_T * state, GstBuffer * buffer)
{
GstVideoGLTextureUploadMeta *meta = NULL;
if (state->current_buffer) {
gst_buffer_unref (state->current_buffer);
} else {
/* Setup the model world */
init_model_proj (state);
TRACE_VC_MEMORY ("after init_model_proj");
/* initialize the OGLES texture(s) */
init_textures (state, buffer);
TRACE_VC_MEMORY ("after init_textures");
}
state->current_buffer = gst_buffer_ref (buffer);
TRACE_VC_MEMORY_ONCE_FOR_ID ("before GstVideoGLTextureUploadMeta", gid0);
if ((meta = gst_buffer_get_video_gl_texture_upload_meta (buffer))) {
if (state->can_avoid_upload) {
GstMemory *mem = gst_buffer_peek_memory (state->current_buffer, 0);
g_assert (gst_is_gl_memory (mem));
state->tex = ((GstGLMemory *) mem)->tex_id;
} else if ((meta = gst_buffer_get_video_gl_texture_upload_meta (buffer))) {
if (meta->n_textures == 1) {
guint ids[4] = { state->tex, 0, 0, 0 };
if (!gst_video_gl_texture_upload_meta_upload (meta, ids)) {
GST_WARNING ("failed to upload eglimage to texture");
GST_WARNING ("failed to upload to texture");
}
}
}
@ -621,6 +842,10 @@ terminate_intercom (APP_STATE_T * state)
static void
flush_internal (APP_STATE_T * state)
{
if (state->current_buffer) {
gst_buffer_unref (state->current_buffer);
}
state->current_buffer = NULL;
}
static void
@ -816,6 +1041,17 @@ events_cb (GstPad * pad, GstPadProbeInfo * probe_info, gpointer user_data)
GstEvent *event = GST_PAD_PROBE_INFO_EVENT (probe_info);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CAPS:
{
if (state->caps) {
gst_caps_unref (state->caps);
state->caps = NULL;
}
gst_event_parse_caps (event, &state->caps);
if (state->caps)
gst_caps_ref (state->caps);
break;
}
case GST_EVENT_FLUSH_START:
flush_start (state);
break;
@ -845,7 +1081,7 @@ query_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
case GST_QUERY_ALLOCATION:
{
platform = gst_gl_platform_to_string (GST_GL_PLATFORM_EGL);
gl_apis = gst_gl_api_to_string (GST_GL_API_GLES1);
gl_apis = gst_gl_api_to_string (GST_GL_API_GLES2);
external_gl_context_desc =
gst_structure_new ("GstVideoGLTextureUploadMeta",
@ -853,8 +1089,7 @@ query_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
"gst.gl.context.type", G_TYPE_STRING, platform,
"gst.gl.context.apis", G_TYPE_STRING, gl_apis, NULL);
gst_query_add_allocation_meta (query,
GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE,
NULL /*external_gl_context_desc */ );
GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, external_gl_context_desc);
gst_structure_free (external_gl_context_desc);
g_free (gl_apis);
@ -864,13 +1099,17 @@ query_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
return GST_PAD_PROBE_OK;
break;
}
case GST_QUERY_CONTEXT:
{
return gst_gl_handle_context_query (state->pipeline, query,
(GstGLDisplay **) & state->gst_display);
break;
}
case GST_QUERY_DRAIN:
{
flush_internal (state);
break;
}
default:
break;
}
@ -884,8 +1123,10 @@ init_playbin_player (APP_STATE_T * state, const gchar * uri)
GstPad *pad = NULL;
GstPad *ghostpad = NULL;
GstElement *vbin = gst_bin_new ("vbin");
/* FIXME replace it by glcolorscale */
GstElement *glfilter = gst_element_factory_make ("gleffects", "glfilter");
/* insert a gl filter so that the GstGLBufferPool
* is managed automatically */
GstElement *glfilter = gst_element_factory_make ("glcolorscale", "glfilter");
GstElement *vsink = gst_element_factory_make ("fakesink", "vsink");
g_object_set (vsink, "sync", TRUE, "silent", TRUE, "qos", TRUE,
"enable-last-sample", FALSE,
@ -901,22 +1142,22 @@ init_playbin_player (APP_STATE_T * state, const gchar * uri)
gst_object_unref (pad);
gst_element_add_pad (vbin, ghostpad);
gst_pad_add_probe (ghostpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, events_cb,
state, NULL);
gst_pad_add_probe (ghostpad, GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM, query_cb,
state, NULL);
pad = gst_element_get_static_pad (vsink, "sink");
gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, events_cb, state,
NULL);
gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM, query_cb, state,
NULL);
gst_object_unref (pad);
gst_element_link (glfilter, vsink);
// FIXME unref ghostpad ?
/* Instantiate and configure playbin */
state->pipeline = gst_element_factory_make ("playbin", "player");
g_object_set (state->pipeline, "uri", uri,
"video-sink", vbin, "flags",
GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_AUDIO, NULL);
state->vsink = gst_object_ref (vsink); // FIXME vbin ?
state->vsink = gst_object_ref (vsink);
return TRUE;
}
@ -926,7 +1167,7 @@ init_parse_launch_player (APP_STATE_T * state, const gchar * spipeline)
GstElement *vsink;
GError *error = NULL;
// FIXME handle parse
// TODO handle parse
state->pipeline = gst_parse_launch (spipeline, &error);
@ -1155,6 +1396,22 @@ close_ogl (void)
DISPMANX_UPDATE_HANDLE_T dispman_update;
#endif
if (state->fshader) {
glDeleteShader (state->fshader);
glDetachShader (state->program, state->fshader);
}
if (state->vshader) {
glDeleteShader (state->vshader);
glDetachShader (state->program, state->vshader);
}
if (state->program)
glDeleteProgram (state->program);
if (state->tex)
glDeleteTextures (1, &state->tex);
/* clear screen */
glClear (GL_COLOR_BUFFER_BIT);
eglSwapBuffers (state->display, state->surface);
@ -1186,20 +1443,12 @@ open_ogl (void)
TRACE_VC_MEMORY ("after bcm_host_init");
#endif
/* Start OpenGLES */
/* Create surface and gl context */
init_ogl (state);
TRACE_VC_MEMORY ("after init_ogl");
/* Wrap the EGLDisplay to GstGLDisplayEGL */
state->gst_display = gst_gl_display_egl_new_with_egl_display (state->display);
/* Setup the model world */
init_model_proj (state);
TRACE_VC_MEMORY ("after init_model_proj");
/* initialize the OGLES texture(s) */
init_textures (state);
TRACE_VC_MEMORY ("after init_textures");
}
static gpointer
@ -1234,6 +1483,7 @@ main (int argc, char **argv)
memset (state, 0, sizeof (*state));
state->animate = TRUE;
state->current_buffer = NULL;
state->caps = NULL;
#if !GLIB_CHECK_VERSION (2, 31, 0)
/* must initialise the threading system before using any other GLib funtion */
@ -1344,6 +1594,11 @@ done:
state->running = FALSE;
g_thread_join (rthread);
if (state->caps) {
gst_caps_unref (state->caps);
state->caps = NULL;
}
terminate_intercom (state);
TRACE_VC_MEMORY ("at exit");