From 753dfca775514ebc049b9b109e2f39d5b73c4bf7 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Thu, 31 Jan 2013 23:43:52 +1100 Subject: [PATCH] [661/906] glass: port to non-glew + shader matrices --- gst/gl/gstglfilterglass.c | 267 ++++++++++++++++++++++++-------------- gst/gl/gstglfilterglass.h | 2 + 2 files changed, 174 insertions(+), 95 deletions(-) diff --git a/gst/gl/gstglfilterglass.c b/gst/gl/gstglfilterglass.c index 619ca69b05..5bb424285e 100644 --- a/gst/gl/gstglfilterglass.c +++ b/gst/gl/gstglfilterglass.c @@ -70,34 +70,80 @@ static gboolean gst_gl_filter_glass_filter_texture (GstGLFilter * filter, static void gst_gl_filter_glass_draw_background_gradient (); static void gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter, gint width, gint height, guint texture, gfloat center_x, gfloat center_y, - gfloat start_alpha, gfloat stop_alpha, gboolean reversed); + gfloat start_alpha, gfloat stop_alpha, gboolean reversed, gfloat rotation); -static void gst_gl_filter_glass_callback (gint width, gint height, - guint texture, gpointer stuff); +static void gst_gl_filter_glass_callback (gpointer stuff); +/* *INDENT-OFF* */ static const gchar *glass_fragment_source = "#extension GL_ARB_texture_rectangle : enable\n" - "uniform sampler2DRect tex;" - "uniform float width, height;" - "void main () {" - " float p = 0.0525;" - " float L1 = p*width;" - " float L2 = width - L1;" - " float L3 = height - L1;" - " float w = 1.0;" - " float r = L1;" - " if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y < L1)" - " r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L1) * (gl_TexCoord[0].y - L1) );" - " else if (gl_TexCoord[0].x > L2 && gl_TexCoord[0].y < L1)" - " r = sqrt( (gl_TexCoord[0].x - L2) * (gl_TexCoord[0].x - L2) + (gl_TexCoord[0].y - L1) * (gl_TexCoord[0].y - L1) );" - " else if (gl_TexCoord[0].x > L2 && gl_TexCoord[0].y > L3)" - " r = sqrt( (gl_TexCoord[0].x - L2) * (gl_TexCoord[0].x - L2) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );" - " else if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y > L3)" - " r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );" - " if (r > L1)" - " w = 0.0;" - " vec4 color = texture2DRect (tex, gl_TexCoord[0].st);" - " gl_FragColor = vec4(color.rgb, gl_Color.a * w);" "}"; + "uniform sampler2DRect tex;\n" + "uniform float width, height;\n" + "varying float alpha;\n" + "void main () {\n" + " float p = 0.0525;\n" + " float L1 = p*width;\n" + " float L2 = width - L1;\n" + " float L3 = height - L1;\n" + " float w = 1.0;\n" + " float r = L1;\n" + " if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y < L1)\n" + " r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L1) * (gl_TexCoord[0].y - L1) );\n" + " else if (gl_TexCoord[0].x > L2 && gl_TexCoord[0].y < L1)\n" + " r = sqrt( (gl_TexCoord[0].x - L2) * (gl_TexCoord[0].x - L2) + (gl_TexCoord[0].y - L1) * (gl_TexCoord[0].y - L1) );\n" + " else if (gl_TexCoord[0].x > L2 && gl_TexCoord[0].y > L3)\n" + " r = sqrt( (gl_TexCoord[0].x - L2) * (gl_TexCoord[0].x - L2) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );\n" + " else if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y > L3)\n" + " r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );\n" + " if (r > L1)\n" + " w = 0.0;\n" + " vec4 color = texture2DRect (tex, gl_TexCoord[0].st);\n" + " gl_FragColor = vec4(color.rgb, alpha * w);\n" + "}\n"; + +static const gchar *glass_vertex_source = + "uniform float yrot;\n" + "uniform float width, height;\n" + "const float fovy = 80.0;\n" + "const float znear = 1.0;\n" + "const float zfar = 5000.0;\n" + "varying float alpha;\n" + "void main () {\n" + " float f = 1.0/(tan(radians(fovy/2.0)));\n" + " float rot = radians (yrot);\n" + " float aspect = width/height;\n" + " // replacement for gluPerspective\n" + " mat4 perspective = mat4 (\n" + " f/aspect, 0.0, 0.0, 0.0,\n" + " 0.0, f, 0.0, 0.0,\n" + " 0.0, 0.0, (znear+zfar)/(znear-zfar), 2.0*znear*zfar/(znear-zfar),\n" + " 0.0, 0.0, -1.0, 0.0 );\n" + " mat4 trans = mat4 (\n" + " 1.0, 0.0, 0.0, 0.0,\n" + " 0.0, 1.0, 0.0, 0.0,\n" + " 0.0, 0.0, 1.0, -3.0,\n" + " 0.0, 0.0, 0.0, 1.0 );\n" + " mat4 rotation = mat4 (\n" + " cos(rot), 0.0, sin(rot), 0.0,\n" + " 0.0, 1.0, 0.0, 0.0,\n" + " -sin(rot), 0.0, cos(rot), 0.0,\n" + " 0.0, 0.0, 0.0, 1.0 );\n" + " gl_Position = trans * perspective * rotation * gl_ModelViewProjectionMatrix * gl_Vertex;\n" + " gl_TexCoord[0] = gl_MultiTexCoord0;\n" + " alpha = gl_Color.a;\n" + "}\n"; + +static const gchar * passthrough_vertex = + "void main () {\n" + " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" + " gl_FrontColor = gl_Color;\n" + "}\n"; + +static const gchar * passthrough_fragment = + "void main () {\n" + " gl_FragColor = gl_Color;\n" + "}\n"; +/* *INDENT-ON* */ static void gst_gl_filter_glass_class_init (GstGLFilterGlassClass * klass) @@ -135,6 +181,7 @@ gst_gl_filter_glass_reset (GstGLFilter * filter) //blocking call, wait the opengl thread has destroyed the shader gst_gl_display_del_shader (filter->display, glass_filter->shader); + gst_gl_display_del_shader (filter->display, glass_filter->passthrough_shader); } static void @@ -166,30 +213,34 @@ gst_gl_filter_glass_get_property (GObject * object, guint prop_id, static gboolean gst_gl_filter_glass_init_shader (GstGLFilter * filter) { + gboolean ret; GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter); //blocking call, wait the opengl thread has compiled the shader - return gst_gl_display_gen_shader (filter->display, 0, glass_fragment_source, - &glass_filter->shader); + ret = + gst_gl_display_gen_shader (filter->display, glass_vertex_source, + glass_fragment_source, &glass_filter->shader); + if (ret) + ret = + gst_gl_display_gen_shader (filter->display, passthrough_vertex, + passthrough_fragment, &glass_filter->passthrough_shader); + + return ret; } static gboolean gst_gl_filter_glass_filter_texture (GstGLFilter * filter, guint in_tex, guint out_tex) { - gpointer glass_filter = GST_GL_FILTER_GLASS (filter); + GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter); + glass_filter->in_tex = in_tex; //blocking call, use a FBO - gst_gl_display_use_fbo (filter->display, + gst_gl_display_use_fbo_v2 (filter->display, GST_VIDEO_INFO_WIDTH (&filter->out_info), GST_VIDEO_INFO_HEIGHT (&filter->out_info), filter->fbo, filter->depthbuffer, out_tex, - gst_gl_filter_glass_callback, - GST_VIDEO_INFO_WIDTH (&filter->in_info), - GST_VIDEO_INFO_HEIGHT (&filter->in_info), - in_tex, 80, (gdouble) GST_VIDEO_INFO_WIDTH (&filter->out_info) / - (gdouble) GST_VIDEO_INFO_HEIGHT (&filter->out_info), 1.0, 5000.0, - GST_GL_DISPLAY_PROJECTION_PERSPECTIVE, (gpointer) glass_filter); + gst_gl_filter_glass_callback, (gpointer) glass_filter); return TRUE; } @@ -204,92 +255,113 @@ get_time (void) } static void -gst_gl_filter_glass_draw_background_gradient () +gst_gl_filter_glass_draw_background_gradient (GstGLFilterGlass * glass) { - glMatrixMode (GL_PROJECTION); + GstGLFilter *filter = GST_GL_FILTER (glass); + GstGLFuncs *gl = filter->display->gl_vtable; - glPushMatrix (); - glLoadIdentity (); - glOrtho (-100, 100, -100, 100, -1000.0, 1000.0); +/* *INDENT-OFF* */ + gfloat mesh[] = { + /* | Vertex | Color | */ + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 0.8f, 0.0f, 0.0f, 0.0f, 0.2f, 1.0f, + -1.0f, 0.8f, 0.0f, 0.0f, 0.0f, 0.2f, 1.0f, + -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.2f, 1.0f, + 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.2f, 1.0f, + }; +/* *INDENT-ON* */ - glBegin (GL_QUADS); + GLushort indices[] = { + 0, 1, 2, + 0, 2, 3, + 2, 3, 4, + 2, 4, 5 + }; - glColor4f (0.0f, 0.0f, 0.0f, 1.0f); - glVertex2f (-100.0f, -100.0f); - glVertex2f (100.0f, -100.0f); + gl->ClientActiveTexture (GL_TEXTURE0); + gl->EnableClientState (GL_VERTEX_ARRAY); + gl->EnableClientState (GL_COLOR_ARRAY); - glColor4f (0.0f, 0.0f, 0.2f, 1.0f); - glVertex2f (100.0f, 80.0f); - glVertex2f (-100.0f, 80.0f); + gl->VertexPointer (3, GL_FLOAT, 7 * sizeof (gfloat), mesh); + gl->ColorPointer (4, GL_FLOAT, 7 * sizeof (gfloat), &mesh[3]); - glVertex2f (100.0f, 80.0f); - glVertex2f (-100.0f, 80.0f); + gl->DrawElements (GL_TRIANGLES, 12, GL_UNSIGNED_SHORT, indices); - glVertex2f (-100.0f, 100.0f); - glVertex2f (100.0f, 100.0f); - - glEnd (); - glPopMatrix (); - - glMatrixMode (GL_MODELVIEW); + gl->DisableClientState (GL_VERTEX_ARRAY); + gl->DisableClientState (GL_COLOR_ARRAY); } static void gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter, gint width, gint height, guint texture, gfloat center_x, gfloat center_y, - gfloat start_alpha, gfloat stop_alpha, gboolean reversed) + gfloat start_alpha, gfloat stop_alpha, gboolean reversed, gfloat rotation) { GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter); + GstGLFuncs *gl = filter->display->gl_vtable; - gfloat topy; - gfloat bottomy; - if (reversed) { - topy = center_y - 1.0f; - bottomy = center_y + 1.0f; - } else { - topy = center_y + 1.0f; - bottomy = center_y - 1.0f; - } + gfloat w = (gfloat) width; + gfloat h = (gfloat) height; + gfloat topy = reversed ? center_y - 1.0f : center_y + 1.0f; + gfloat bottomy = reversed ? center_y + 1.0f : center_y - 1.0f; - gst_gl_shader_use (glass_filter->shader); +/* *INDENT-OFF* */ + gfloat mesh[] = { + /*| Vertex |TexCoord0| Colour |*/ + center_x-1.6, topy, 0.0, 0.0, h, 1.0, 1.0, 1.0, start_alpha, + center_x+1.6, topy, 0.0, w, h, 1.0, 1.0, 1.0, start_alpha, + center_x+1.6, bottomy, 0.0, w, 0.0, 1.0, 1.0, 1.0, stop_alpha, + center_x-1.6, bottomy, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, stop_alpha, + }; +/* *INDENT-ON* */ - glActiveTextureARB (GL_TEXTURE0_ARB); - glEnable (GL_TEXTURE_RECTANGLE_ARB); - glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); - glDisable (GL_TEXTURE_RECTANGLE_ARB); + GLushort indices[] = { + 0, 1, 2, + 0, 2, 3 + }; + + gl->ActiveTexture (GL_TEXTURE0); + gl->Enable (GL_TEXTURE_RECTANGLE_ARB); + gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); + gl->Disable (GL_TEXTURE_RECTANGLE_ARB); gst_gl_shader_set_uniform_1i (glass_filter->shader, "tex", 0); gst_gl_shader_set_uniform_1f (glass_filter->shader, "width", (gfloat) width); gst_gl_shader_set_uniform_1f (glass_filter->shader, "height", (gfloat) height); + gst_gl_shader_set_uniform_1f (glass_filter->shader, "yrot", rotation); - glBegin (GL_QUADS); - glColor4f (1.0f, 1.0f, 1.0f, start_alpha); - glTexCoord2i (0, height); - glVertex2f (center_x - 1.6f, topy); - glTexCoord2i (width, height); - glVertex2f (center_x + 1.6f, topy); + gl->ClientActiveTexture (GL_TEXTURE0); + gl->EnableClientState (GL_TEXTURE_COORD_ARRAY); + gl->EnableClientState (GL_VERTEX_ARRAY); + gl->EnableClientState (GL_COLOR_ARRAY); - glColor4f (1.0, 1.0, 1.0, stop_alpha); - glTexCoord2i (width, 0); - glVertex2f (center_x + 1.6f, bottomy); - glTexCoord2i (0, 0); - glVertex2f (center_x - 1.6f, bottomy); - glEnd (); + gl->VertexPointer (3, GL_FLOAT, 9 * sizeof (gfloat), mesh); + gl->TexCoordPointer (2, GL_FLOAT, 9 * sizeof (gfloat), &mesh[3]); + gl->ColorPointer (4, GL_FLOAT, 9 * sizeof (gfloat), &mesh[5]); - gst_gl_shader_use (0); + gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); + + gl->DisableClientState (GL_TEXTURE_COORD_ARRAY); + gl->DisableClientState (GL_VERTEX_ARRAY); + gl->DisableClientState (GL_COLOR_ARRAY); } //opengl scene, params: input texture (not the output filter->texture) static void -gst_gl_filter_glass_callback (gint width, gint height, guint texture, - gpointer stuff) +gst_gl_filter_glass_callback (gpointer stuff) { static gint64 start_time = 0; + gfloat rotation; GstGLFilter *filter = GST_GL_FILTER (stuff); GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (stuff); + GstGLFuncs *gl = filter->display->gl_vtable; + + gint width = GST_VIDEO_INFO_WIDTH (&filter->out_info); + gint height = GST_VIDEO_INFO_HEIGHT (&filter->out_info); + guint texture = glass_filter->in_tex; if (start_time == 0) start_time = get_time (); @@ -303,28 +375,33 @@ gst_gl_filter_glass_callback (gint width, gint height, guint texture, } } - glTranslatef (0.0f, 2.0f, -3.0f); - - gst_gl_filter_glass_draw_background_gradient (); + gst_gl_shader_use (glass_filter->passthrough_shader); + gst_gl_filter_glass_draw_background_gradient (glass_filter); //Rotation if (start_time != 0) { gint64 time_passed = get_time () - start_time; - glRotated (sin (time_passed / 1200000.0) * 45.0, 0.0, 1.0, 0.0); + rotation = sin (time_passed / 1200000.0) * 45.0f; + } else { + rotation = 0.0f; } - glEnable (GL_BLEND); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl->Enable (GL_BLEND); + gl->BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + gst_gl_shader_use (glass_filter->shader); //Reflection gst_gl_filter_glass_draw_video_plane (filter, width, height, texture, - 0.0f, 0.0f, 0.3f, 0.0f, TRUE); + 0.0f, 2.0f, 0.3f, 0.0f, TRUE, rotation); //Main video gst_gl_filter_glass_draw_video_plane (filter, width, height, texture, - 0.0f, -2.0f, 1.0f, 1.0f, FALSE); + 0.0f, 0.0f, 1.0f, 1.0f, FALSE, rotation); - glDisable (GL_TEXTURE_RECTANGLE_ARB); - glDisable (GL_BLEND); + gst_gl_display_clear_shader (filter->display); + + gl->Disable (GL_TEXTURE_RECTANGLE_ARB); + gl->Disable (GL_BLEND); } diff --git a/gst/gl/gstglfilterglass.h b/gst/gl/gstglfilterglass.h index e6f65af5da..9e7cf9bf49 100644 --- a/gst/gl/gstglfilterglass.h +++ b/gst/gl/gstglfilterglass.h @@ -38,8 +38,10 @@ typedef struct _GstGLFilterGlassClass GstGLFilterGlassClass; struct _GstGLFilterGlass { GstGLFilter filter; + GstGLShader *passthrough_shader; GstGLShader *shader; gint64 timestamp; + guint in_tex; }; struct _GstGLFilterGlassClass