summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Isorce <julien.isorce@collabora.co.uk>2014-04-25 17:32:16 +0100
committerJulien Isorce <julien.isorce@collabora.co.uk>2014-06-25 10:50:54 +0100
commit31cd1fd77b893c6273c447e972f1fe975d188605 (patch)
tree4eba75dad0f82b669206312de8f0a9475ab67a23
parentf1c76ef92112acc7855d5715ac149a3620559f6a (diff)
downloadgst-omx-31cd1fd77b893c6273c447e972f1fe975d188605.tar.gz
testegl: convert code from GLESv1 to GLESv2
See https://bugzilla.gnome.org/show_bug.cgi?id=728940
-rw-r--r--examples/egl/Makefile.am3
-rw-r--r--examples/egl/cube_texture_and_coords.h50
-rw-r--r--examples/egl/testegl.c519
3 files changed, 414 insertions, 158 deletions
diff --git a/examples/egl/Makefile.am b/examples/egl/Makefile.am
index 8dc7027..2646cba 100644
--- a/examples/egl/Makefile.am
+++ b/examples/egl/Makefile.am
@@ -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) \
diff --git a/examples/egl/cube_texture_and_coords.h b/examples/egl/cube_texture_and_coords.h
index 663e23b..1832df3 100644
--- a/examples/egl/cube_texture_and_coords.h
+++ b/examples/egl/cube_texture_and_coords.h
@@ -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. */
diff --git a/examples/egl/testegl.c b/examples/egl/testegl.c
index 727b655..5dbb9b4 100644
--- a/examples/egl/testegl.c
+++ b/examples/egl/testegl.c
@@ -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;
+
+ 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);
- glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+ 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);
}
/***********************************************************
@@ -460,32 +656,6 @@ inc_and_wrap_angle (GLfloat angle, GLfloat angle_inc)
}
/***********************************************************
- * 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
*
* Arguments:
@@ -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);
-
- glBindTexture (GL_TEXTURE_2D, state->tex);
+ GstCapsFeatures *feature = gst_caps_get_features (state->caps, 0);
+
+ 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");