2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) <2016> Matthew Waters <matthew@centricular.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
25 #include <gst/gl/gstglfuncs.h>
27 #include "gltestsrc.h"
29 #define MAX_ATTRIBUTES 4
31 struct vts_color_struct
38 gfloat X, Y, Z, W, R, G, B;
57 static const struct vts_color_struct vts_colors[] = {
81 {19. / 256.0f, 19. / 256.0f, 19. / 256.0},
85 static const GLfloat positions[] = {
92 static const GLushort indices_quad[] = { 0, 1, 2, 0, 2, 3 };
101 guint offset; /* in bytes */
102 guint stride; /* in bytes */
107 struct BaseSrcImpl base;
116 struct attribute attributes[MAX_ATTRIBUTES];
118 gconstpointer vertices;
120 const gushort *indices;
126 _bind_buffer (struct SrcShader *src)
128 GstGLContext *context = src->base.context;
129 const GstGLFuncs *gl = context->gl_vtable;
132 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, src->vbo_indices);
133 gl->BindBuffer (GL_ARRAY_BUFFER, src->vbo);
135 /* Load the vertex position */
136 for (i = 0; i < src->n_attributes; i++) {
137 struct attribute *attr = &src->attributes[i];
139 if (attr->location == -1)
141 gst_gl_shader_get_attribute_location (src->shader, attr->name);
143 gl->VertexAttribPointer (attr->location, attr->n_elements,
144 attr->element_type, GL_FALSE, attr->stride,
145 (void *) (gintptr) attr->offset);
147 gl->EnableVertexAttribArray (attr->location);
152 _unbind_buffer (struct SrcShader *src)
154 GstGLContext *context = src->base.context;
155 const GstGLFuncs *gl = context->gl_vtable;
158 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
159 gl->BindBuffer (GL_ARRAY_BUFFER, 0);
161 for (i = 0; i < src->n_attributes; i++) {
162 struct attribute *attr = &src->attributes[i];
164 gl->DisableVertexAttribArray (attr->location);
169 _src_shader_init (gpointer impl, GstGLContext * context, GstVideoInfo * v_info)
171 struct SrcShader *src = impl;
172 const GstGLFuncs *gl = context->gl_vtable;
174 src->base.context = context;
177 if (gl->GenVertexArrays) {
178 gl->GenVertexArrays (1, &src->vao);
179 gl->BindVertexArray (src->vao);
182 gl->GenBuffers (1, &src->vbo);
183 gl->BindBuffer (GL_ARRAY_BUFFER, src->vbo);
184 gl->BufferData (GL_ARRAY_BUFFER, src->vertices_size,
185 src->vertices, GL_STATIC_DRAW);
187 gl->GenBuffers (1, &src->vbo_indices);
188 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, src->vbo_indices);
189 gl->BufferData (GL_ELEMENT_ARRAY_BUFFER, src->n_indices * sizeof (gushort),
190 src->indices, GL_STATIC_DRAW);
192 if (gl->GenVertexArrays) {
194 gl->BindVertexArray (0);
197 gl->BindBuffer (GL_ARRAY_BUFFER, 0);
198 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
205 _src_shader_fill_bound_fbo (gpointer impl)
207 struct SrcShader *src = impl;
208 const GstGLFuncs *gl;
210 g_return_val_if_fail (src->base.context, FALSE);
211 g_return_val_if_fail (src->shader, FALSE);
212 gl = src->base.context->gl_vtable;
214 gst_gl_shader_use (src->shader);
216 if (gl->GenVertexArrays)
217 gl->BindVertexArray (src->vao);
220 gl->DrawElements (GL_TRIANGLES, src->n_indices, GL_UNSIGNED_SHORT,
221 (gpointer) (gintptr) src->index_offset);
223 if (gl->GenVertexArrays)
224 gl->BindVertexArray (0);
225 _unbind_buffer (src);
227 gst_gl_context_clear_shader (src->base.context);
233 _src_shader_deinit (gpointer impl)
235 struct SrcShader *src = impl;
236 const GstGLFuncs *gl = src->base.context->gl_vtable;
239 gst_object_unref (src->shader);
243 gl->DeleteVertexArrays (1, &src->vao);
247 gl->DeleteBuffers (1, &src->vbo);
250 if (src->vbo_indices)
251 gl->DeleteBuffers (1, &src->vbo_indices);
252 src->vbo_indices = 0;
256 static const gchar *smpte_vertex_src =
257 "attribute vec4 position;\n"
258 "attribute vec4 a_color;\n"
259 "varying vec4 color;\n"
262 " gl_Position = position;\n"
263 " color = a_color;\n"
266 static const gchar *smpte_fragment_src =
268 "precision mediump float;\n"
270 "varying vec4 color;\n"
273 " gl_FragColor = color;\n"
276 static const gchar *snow_vertex_src =
277 "attribute vec4 position;\n"
278 "varying vec2 out_uv;\n"
281 " gl_Position = position;\n"
282 " out_uv = position.xy;\n"
285 static const gchar *snow_fragment_src =
287 "precision mediump float;\n"
289 "uniform float time;\n"
290 "varying vec2 out_uv;\n"
292 "float rand(vec2 co){\n"
293 " return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453);\n"
297 " gl_FragColor = vec4(rand(time * out_uv));\n"
304 struct SrcShader base;
306 GstGLShader *snow_shader;
307 GstGLShader *color_shader;
308 gint attr_snow_position;
312 _src_smpte_new (GstGLTestSrc * test)
314 struct SrcSMPTE *src = g_new0 (struct SrcSMPTE, 1);
316 src->base.base.src = test;
322 _src_smpte_init (gpointer impl, GstGLContext * context, GstVideoInfo * v_info)
324 struct SrcSMPTE *src = impl;
325 struct XYZWRGB *coord;
326 gushort *plane_indices;
327 GError *error = NULL;
331 src->base.base.context = context;
333 coord = g_new0 (struct XYZWRGB, N_QUADS * 4);
334 plane_indices = g_new0 (gushort, N_QUADS * 6);
337 for (i = 0; i < 7; i++) {
338 coord[color_idx * 4 + 0].X = -1.0f + i * (2.0f / 7.0f);
339 coord[color_idx * 4 + 0].Y = 1.0f / 3.0f;
340 coord[color_idx * 4 + 1].X = -1.0f + (i + 1) * (2.0f / 7.0f);
341 coord[color_idx * 4 + 1].Y = 1.0f / 3.0f;
342 coord[color_idx * 4 + 2].X = -1.0f + (i + 1) * (2.0f / 7.0f);
343 coord[color_idx * 4 + 2].Y = -1.0f;
344 coord[color_idx * 4 + 3].X = -1.0f + i * (2.0f / 7.0f);
345 coord[color_idx * 4 + 3].Y = -1.0f;
350 for (i = 0; i < 7; i++) {
351 coord[color_idx * 4 + 0].X = -1.0f + i * (2.0f / 7.0f);
352 coord[color_idx * 4 + 0].Y = 0.5f;
353 coord[color_idx * 4 + 1].X = -1.0f + (i + 1) * (2.0f / 7.0f);
354 coord[color_idx * 4 + 1].Y = 0.5f;
355 coord[color_idx * 4 + 2].X = -1.0f + (i + 1) * (2.0f / 7.0f);
356 coord[color_idx * 4 + 2].Y = 1.0f / 3.0f;
357 coord[color_idx * 4 + 3].X = -1.0f + i * (2.0f / 7.0f);
358 coord[color_idx * 4 + 3].Y = 1.0f / 3.0f;
362 /* bottom row, left three */
363 for (i = 0; i < 3; i++) {
364 coord[color_idx * 4 + 0].X = -1.0f + i / 3.0f;
365 coord[color_idx * 4 + 0].Y = 1.0f;
366 coord[color_idx * 4 + 1].X = -1.0f + (i + 1) / 3.0f;
367 coord[color_idx * 4 + 1].Y = 1.0f;
368 coord[color_idx * 4 + 2].X = -1.0f + (i + 1) / 3.0f;
369 coord[color_idx * 4 + 2].Y = 0.5f;
370 coord[color_idx * 4 + 3].X = -1.0f + i / 3.0f;
371 coord[color_idx * 4 + 3].Y = 0.5f;
375 /* bottom row, middle three (the blacks) */
376 for (i = 0; i < 3; i++) {
377 coord[color_idx * 4 + 0].X = i / 6.0f;
378 coord[color_idx * 4 + 0].Y = 1.0f;
379 coord[color_idx * 4 + 1].X = (i + 1) / 6.0f;
380 coord[color_idx * 4 + 1].Y = 1.0f;
381 coord[color_idx * 4 + 2].X = (i + 1) / 6.0f;
382 coord[color_idx * 4 + 2].Y = 0.5f;
383 coord[color_idx * 4 + 3].X = i / 6.0f;
384 coord[color_idx * 4 + 3].Y = 0.5f;
388 g_assert (color_idx < N_QUADS);
390 for (i = 0; i < N_QUADS - 1; i++) {
394 } else if ((i - 7) & 1) {
402 } else if (i == 15) {
404 } else if (i == 16) {
406 } else if (i == 17) {
407 k = COLOR_SUPER_BLACK;
408 } else if (i == 18) {
410 } else if (i == 19) {
414 for (j = 0; j < 4; j++) {
415 coord[i * 4 + j].Z = 0.0f;
416 coord[i * 4 + j].W = 1.0f;
417 coord[i * 4 + j].R = vts_colors[k].R;
418 coord[i * 4 + j].G = vts_colors[k].G;
419 coord[i * 4 + j].B = vts_colors[k].B;
422 for (j = 0; j < 6; j++)
423 plane_indices[i * 6 + j] = i * 4 + indices_quad[j];
427 coord[color_idx * 4 + 0].X = 0.5f;
428 coord[color_idx * 4 + 0].Y = 1.0f;
429 coord[color_idx * 4 + 0].Z = 0.0f;
430 coord[color_idx * 4 + 0].W = 1.0f;
431 coord[color_idx * 4 + 1].X = 1.0f;
432 coord[color_idx * 4 + 1].Y = 1.0f;
433 coord[color_idx * 4 + 1].Z = 0.0f;
434 coord[color_idx * 4 + 1].W = 1.0f;
435 coord[color_idx * 4 + 2].X = 1.0f;
436 coord[color_idx * 4 + 2].Y = 0.5f;
437 coord[color_idx * 4 + 2].Z = 0.0f;
438 coord[color_idx * 4 + 2].W = 1.0f;
439 coord[color_idx * 4 + 3].X = 0.5f;
440 coord[color_idx * 4 + 3].Y = 0.5f;
441 coord[color_idx * 4 + 3].Z = 0.0f;
442 coord[color_idx * 4 + 3].W = 1.0f;
443 for (i = 0; i < 6; i++)
444 plane_indices[color_idx * 6 + i] = color_idx * 4 + indices_quad[i];
447 if (src->color_shader)
448 gst_object_unref (src->color_shader);
449 src->color_shader = gst_gl_shader_new_link_with_stages (context, &error,
450 gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER,
451 GST_GLSL_VERSION_NONE,
452 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
454 gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
455 GST_GLSL_VERSION_NONE,
456 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
457 smpte_fragment_src), NULL);
458 if (!src->color_shader) {
459 GST_ERROR_OBJECT (src->base.base.src, "%s", error->message);
463 if (src->snow_shader)
464 gst_object_unref (src->snow_shader);
465 src->snow_shader = gst_gl_shader_new_link_with_stages (context, &error,
466 gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER,
467 GST_GLSL_VERSION_NONE,
468 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
470 gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
471 GST_GLSL_VERSION_NONE,
472 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
473 snow_fragment_src), NULL);
474 if (!src->snow_shader) {
475 GST_ERROR_OBJECT (src->base.base.src, "%s", error->message);
479 src->attr_snow_position = -1;
481 src->base.n_attributes = 2;
483 src->base.attributes[0].name = "position";
484 src->base.attributes[0].location = -1;
485 src->base.attributes[0].n_elements = 4;
486 src->base.attributes[0].element_type = GL_FLOAT;
487 src->base.attributes[0].offset = 0;
488 src->base.attributes[0].stride = sizeof (struct XYZWRGB);
490 src->base.attributes[1].name = "a_color";
491 src->base.attributes[1].location = -1;
492 src->base.attributes[1].n_elements = 3;
493 src->base.attributes[1].element_type = GL_FLOAT;
494 src->base.attributes[1].offset = 4 * sizeof (gfloat);
495 src->base.attributes[1].stride = sizeof (struct XYZWRGB);
497 if (src->base.shader)
498 gst_object_unref (src->base.shader);
499 src->base.shader = gst_object_ref (src->color_shader);
500 src->base.vertices = (gfloat *) coord;
501 src->base.vertices_size = sizeof (struct XYZWRGB) * N_QUADS * 4;
502 src->base.indices = plane_indices;
503 src->base.n_indices = N_QUADS * 6;
505 return _src_shader_init (impl, context, v_info);
509 _src_smpte_fill_bound_fbo (gpointer impl)
511 struct SrcSMPTE *src = impl;
512 gint attr_color_position = -1;
514 src->base.n_attributes = 2;
515 if (src->base.shader)
516 gst_object_unref (src->base.shader);
517 src->base.shader = gst_object_ref (src->color_shader);
518 src->base.n_indices = (N_QUADS - 1) * 6;
519 src->base.index_offset = 0;
520 if (!_src_shader_fill_bound_fbo (impl))
522 attr_color_position = src->base.attributes[0].location;
524 src->base.attributes[0].location = src->attr_snow_position;
525 src->base.n_attributes = 1;
526 if (src->base.shader)
527 gst_object_unref (src->base.shader);
528 src->base.shader = gst_object_ref (src->snow_shader);
529 src->base.n_indices = 6;
530 src->base.index_offset = (N_QUADS - 1) * 6 * sizeof (gushort);
531 gst_gl_shader_use (src->snow_shader);
532 gst_gl_shader_set_uniform_1f (src->snow_shader, "time",
533 (gfloat) src->base.base.src->running_time / GST_SECOND);
534 if (!_src_shader_fill_bound_fbo (impl))
536 src->attr_snow_position = src->base.attributes[0].location;
537 src->base.attributes[0].location = attr_color_position;
543 _src_smpte_free (gpointer impl)
545 struct SrcSMPTE *src = impl;
550 _src_shader_deinit (impl);
552 g_free ((gpointer) src->base.vertices);
553 g_free ((gpointer) src->base.indices);
555 if (src->snow_shader)
556 gst_object_unref (src->snow_shader);
557 if (src->color_shader)
558 gst_object_unref (src->color_shader);
563 static const struct SrcFuncs src_smpte = {
564 GST_GL_TEST_SRC_SMPTE,
567 _src_smpte_fill_bound_fbo,
575 struct BaseSrcImpl base;
577 struct vts_color_struct color;
581 _src_uni_color_new (GstGLTestSrc * test)
583 struct SrcUniColor *src = g_new0 (struct SrcUniColor, 1);
585 src->base.src = test;
591 _src_uni_color_init (gpointer impl, GstGLContext * context,
592 GstVideoInfo * v_info)
594 struct SrcUniColor *src = impl;
596 src->base.context = context;
597 src->base.v_info = *v_info;
603 _src_uni_color_fill_bound_fbo (gpointer impl)
605 struct SrcUniColor *src = impl;
606 const GstGLFuncs *gl = src->base.context->gl_vtable;
608 gl->ClearColor (src->color.R, src->color.G, src->color.B, 1.0f);
609 gl->Clear (GL_COLOR_BUFFER_BIT);
615 _src_uni_color_free (gpointer impl)
620 #define SRC_UNICOLOR(name, cap_name) \
622 G_PASTE(G_PASTE(_src_unicolor_,name),_new) (GstGLTestSrc * test) \
624 struct SrcUniColor *src = _src_uni_color_new (test); \
625 src->color = vts_colors[G_PASTE(COLOR_,cap_name)]; \
628 static const struct SrcFuncs G_PASTE (src_,name) = { \
629 G_PASTE(GST_GL_TEST_SRC_,cap_name), \
630 G_PASTE(G_PASTE(_src_unicolor_,name),_new), \
631 _src_uni_color_init, \
632 _src_uni_color_fill_bound_fbo, \
633 _src_uni_color_free, \
636 SRC_UNICOLOR (white, WHITE);
637 SRC_UNICOLOR (black, BLACK);
638 SRC_UNICOLOR (red, RED);
639 SRC_UNICOLOR (green, GREEN);
640 SRC_UNICOLOR (blue, BLUE);
643 _src_blink_new (GstGLTestSrc * test)
645 struct SrcUniColor *src = _src_uni_color_new (test);
647 src->color = vts_colors[COLOR_WHITE];
653 _src_blink_fill_bound_fbo (gpointer impl)
655 struct SrcUniColor *src = impl;
657 if (src->color.R > 0.5) {
658 src->color = vts_colors[COLOR_BLACK];
660 src->color = vts_colors[COLOR_WHITE];
663 return _src_uni_color_fill_bound_fbo (impl);
666 static const struct SrcFuncs src_blink = {
667 GST_GL_TEST_SRC_BLINK,
670 _src_blink_fill_bound_fbo,
675 static const gchar *checkers_vertex_src = "attribute vec4 position;\n"
679 " gl_Position = position;\n"
680 /* RPi gives incorrect results for positive uv (plus it makes us start on
681 * the right pixel color i.e. red) */
682 " uv = position.xy - 1.0;\n"
685 static const gchar *checkers_fragment_src =
687 "precision mediump float;\n"
689 "uniform float checker_width;\n"
690 "uniform float width;\n"
691 "uniform float height;\n"
695 " vec2 xy_mod = floor (0.5 * uv * vec2(width, height) / (checker_width));\n"
696 " float result = mod (xy_mod.x + xy_mod.y, 2.0);\n"
697 " gl_FragColor.r = step (result, 0.5);\n"
698 " gl_FragColor.g = 1.0 - gl_FragColor.r;\n"
699 " gl_FragColor.ba = vec2(0.0, 1.0);\n"
705 struct SrcShader base;
711 _src_checkers_init (gpointer impl, GstGLContext * context,
712 GstVideoInfo * v_info)
714 struct SrcCheckers *src = impl;
715 GError *error = NULL;
717 src->base.base.context = context;
719 if (src->base.shader)
720 gst_object_unref (src->base.shader);
721 src->base.shader = gst_gl_shader_new_link_with_stages (context, &error,
722 gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER,
723 GST_GLSL_VERSION_NONE,
724 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
725 checkers_vertex_src),
726 gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
727 GST_GLSL_VERSION_NONE,
728 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
729 checkers_fragment_src), NULL);
730 if (!src->base.shader) {
731 GST_ERROR_OBJECT (src->base.base.src, "%s", error->message);
735 src->base.n_attributes = 1;
737 src->base.attributes[0].name = "position";
738 src->base.attributes[0].location = -1;
739 src->base.attributes[0].n_elements = 4;
740 src->base.attributes[0].element_type = GL_FLOAT;
741 src->base.attributes[0].offset = 0;
742 src->base.attributes[0].stride = 4 * sizeof (gfloat);
744 src->base.vertices = positions;
745 src->base.vertices_size = sizeof (positions);
746 src->base.indices = indices_quad;
747 src->base.n_indices = 6;
749 gst_gl_shader_use (src->base.shader);
750 gst_gl_shader_set_uniform_1f (src->base.shader, "checker_width",
752 gst_gl_shader_set_uniform_1f (src->base.shader, "width",
753 (gfloat) GST_VIDEO_INFO_WIDTH (v_info));
754 gst_gl_shader_set_uniform_1f (src->base.shader, "height",
755 (gfloat) GST_VIDEO_INFO_HEIGHT (v_info));
756 gst_gl_context_clear_shader (src->base.base.context);
758 return _src_shader_init (impl, context, v_info);
762 _src_checkers_free (gpointer impl)
764 struct SrcCheckers *src = impl;
769 _src_shader_deinit (impl);
775 _src_checkers_new (GstGLTestSrc * test)
777 struct SrcCheckers *src = g_new0 (struct SrcCheckers, 1);
779 src->base.base.src = test;
784 #define SRC_CHECKERS(spacing) \
786 G_PASTE(G_PASTE(_src_checkers,spacing),_new) (GstGLTestSrc * test) \
788 struct SrcCheckers *src = _src_checkers_new (test); \
789 src->checker_width = spacing; \
792 static const struct SrcFuncs G_PASTE(src_checkers,spacing) = { \
793 G_PASTE(GST_GL_TEST_SRC_CHECKERS,spacing), \
794 G_PASTE(G_PASTE(_src_checkers,spacing),_new), \
795 _src_checkers_init, \
796 _src_shader_fill_bound_fbo, \
797 _src_checkers_free, \
806 _src_snow_init (gpointer impl, GstGLContext * context, GstVideoInfo * v_info)
808 struct SrcShader *src = impl;
809 GError *error = NULL;
811 src->base.context = context;
814 gst_object_unref (src->shader);
815 src->shader = gst_gl_shader_new_link_with_stages (context, &error,
816 gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER,
817 GST_GLSL_VERSION_NONE,
818 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
820 gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
821 GST_GLSL_VERSION_NONE,
822 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
823 snow_fragment_src), NULL);
825 GST_ERROR_OBJECT (src->base.src, "%s", error->message);
829 src->n_attributes = 1;
831 src->attributes[0].name = "position";
832 src->attributes[0].location = -1;
833 src->attributes[0].n_elements = 4;
834 src->attributes[0].element_type = GL_FLOAT;
835 src->attributes[0].offset = 0;
836 src->attributes[0].stride = 4 * sizeof (gfloat);
838 src->vertices = positions;
839 src->vertices_size = sizeof (positions);
840 src->indices = indices_quad;
843 return _src_shader_init (impl, context, v_info);
847 _src_snow_fill_bound_fbo (gpointer impl)
849 struct SrcShader *src = impl;
851 g_return_val_if_fail (src->base.context, FALSE);
852 g_return_val_if_fail (src->shader, FALSE);
854 gst_gl_shader_use (src->shader);
855 gst_gl_shader_set_uniform_1f (src->shader, "time",
856 (gfloat) src->base.src->running_time / GST_SECOND);
858 return _src_shader_fill_bound_fbo (impl);
862 _src_snow_free (gpointer impl)
864 struct SrcShader *src = impl;
869 _src_shader_deinit (impl);
875 _src_snow_new (GstGLTestSrc * test)
877 struct SrcShader *src = g_new0 (struct SrcShader, 1);
879 src->base.src = test;
884 static const struct SrcFuncs src_snow = {
885 GST_GL_TEST_SRC_SNOW,
888 _src_snow_fill_bound_fbo,
893 static const gchar *mandelbrot_vertex_src = "attribute vec4 position;\n"
894 "uniform float aspect_ratio;\n"
895 "varying vec2 fractal_position;\n"
898 " gl_Position = position;\n"
899 " fractal_position = vec2(position.y * 0.5 - 0.3, aspect_ratio * position.x * 0.5);\n"
900 " fractal_position *= 2.5;\n"
903 static const gchar *mandelbrot_fragment_src =
905 "precision mediump float;\n"
907 "uniform float time;\n"
908 "varying vec2 fractal_position;\n"
909 "const vec4 K = vec4(1.0, 0.66, 0.33, 3.0);\n"
910 "vec4 hsv_to_rgb(float hue, float saturation, float value) {\n"
911 " vec4 p = abs(fract(vec4(hue) + K) * 6.0 - K.wwww);\n"
912 " return value * mix(K.xxxx, clamp(p - K.xxxx, 0.0, 1.0), saturation);\n"
914 "vec4 i_to_rgb(int i) {\n"
915 " float hue = float(i) / 100.0 + sin(time);\n"
916 " return hsv_to_rgb(hue, 0.5, 0.8);\n"
918 "vec2 pow_2_complex(vec2 c) {\n"
919 " return vec2(c.x*c.x - c.y*c.y, 2.0 * c.x * c.y);\n"
921 "vec2 mandelbrot(vec2 c, vec2 c0) {\n"
922 " return pow_2_complex(c) + c0;\n"
924 "vec4 iterate_pixel(vec2 position) {\n"
925 " vec2 c = vec2(0);\n"
926 " for (int i=0; i < 20; i++) {\n"
927 " if (c.x*c.x + c.y*c.y > 2.0*2.0)\n"
928 " return i_to_rgb(i);\n"
929 " c = mandelbrot(c, position);\n"
931 " return vec4(0, 0, 0, 1);\n"
934 " gl_FragColor = iterate_pixel(fractal_position);\n"
939 _src_mandelbrot_init (gpointer impl, GstGLContext * context,
940 GstVideoInfo * v_info)
942 struct SrcShader *src = impl;
943 GError *error = NULL;
945 src->base.context = context;
948 gst_object_unref (src->shader);
949 src->shader = gst_gl_shader_new_link_with_stages (context, &error,
950 gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER,
951 GST_GLSL_VERSION_NONE,
952 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
953 mandelbrot_vertex_src),
954 gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
955 GST_GLSL_VERSION_NONE,
956 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
957 mandelbrot_fragment_src), NULL);
959 GST_ERROR_OBJECT (src->base.src, "%s", error->message);
963 src->n_attributes = 1;
965 src->attributes[0].name = "position";
966 src->attributes[0].location = -1;
967 src->attributes[0].n_elements = 4;
968 src->attributes[0].element_type = GL_FLOAT;
969 src->attributes[0].offset = 0;
970 src->attributes[0].stride = 4 * sizeof (gfloat);
972 src->vertices = positions;
973 src->vertices_size = sizeof (positions);
974 src->indices = indices_quad;
977 gst_gl_shader_use (src->shader);
978 gst_gl_shader_set_uniform_1f (src->shader, "aspect_ratio",
979 (gfloat) GST_VIDEO_INFO_WIDTH (v_info) /
980 (gfloat) GST_VIDEO_INFO_HEIGHT (v_info));
981 gst_gl_context_clear_shader (src->base.context);
983 return _src_shader_init (impl, context, v_info);
987 _src_mandelbrot_fill_bound_fbo (gpointer impl)
989 struct SrcShader *src = impl;
991 g_return_val_if_fail (src->base.context, FALSE);
992 g_return_val_if_fail (src->shader, FALSE);
994 gst_gl_shader_use (src->shader);
995 gst_gl_shader_set_uniform_1f (src->shader, "time",
996 (gfloat) src->base.src->running_time / GST_SECOND);
998 return _src_shader_fill_bound_fbo (impl);
1002 _src_mandelbrot_free (gpointer impl)
1004 struct SrcShader *src = impl;
1009 _src_shader_deinit (impl);
1015 _src_mandelbrot_new (GstGLTestSrc * test)
1017 struct SrcShader *src = g_new0 (struct SrcShader, 1);
1019 src->base.src = test;
1024 static const struct SrcFuncs src_mandelbrot = {
1025 GST_GL_TEST_SRC_MANDELBROT,
1026 _src_mandelbrot_new,
1027 _src_mandelbrot_init,
1028 _src_mandelbrot_fill_bound_fbo,
1029 _src_mandelbrot_free,
1033 static const gchar *circular_vertex_src =
1034 "attribute vec4 position;\n"
1035 "varying vec2 uv;\n"
1038 " gl_Position = position;\n"
1039 " uv = position.xy;\n"
1042 static const gchar *circular_fragment_src =
1044 "precision mediump float;\n"
1046 "uniform float aspect_ratio;\n"
1047 "varying vec2 uv;\n"
1048 "#define PI 3.14159265\n"
1050 " float dist = 0.5 * sqrt(uv.x * uv.x + uv.y / aspect_ratio * uv.y / aspect_ratio);\n"
1051 " float seg = floor(dist * 16.0);\n"
1052 " if (seg <= 0.0 || seg >= 8.0) {\n"
1053 " gl_FragColor = vec4(vec3(0.0), 1.0);\n"
1055 " float d = floor (256.0 * dist * 200.0 * pow (2.0, - (seg - 1.0) / 4.0) + 0.5) / 128.0;\n"
1056 " gl_FragColor = vec4 (vec3(sin (d * PI) * 0.5 + 0.5), 1.0);\n"
1062 _src_circular_init (gpointer impl, GstGLContext * context,
1063 GstVideoInfo * v_info)
1065 struct SrcShader *src = impl;
1066 GError *error = NULL;
1068 src->base.context = context;
1071 gst_object_unref (src->shader);
1072 src->shader = gst_gl_shader_new_link_with_stages (context, &error,
1073 gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER,
1074 GST_GLSL_VERSION_NONE,
1075 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
1076 circular_vertex_src),
1077 gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
1078 GST_GLSL_VERSION_NONE,
1079 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
1080 circular_fragment_src), NULL);
1082 GST_ERROR_OBJECT (src->base.src, "%s", error->message);
1086 src->n_attributes = 1;
1088 src->attributes[0].name = "position";
1089 src->attributes[0].location = -1;
1090 src->attributes[0].n_elements = 4;
1091 src->attributes[0].element_type = GL_FLOAT;
1092 src->attributes[0].offset = 0;
1093 src->attributes[0].stride = 4 * sizeof (gfloat);
1095 src->vertices = positions;
1096 src->vertices_size = sizeof (positions);
1097 src->indices = indices_quad;
1100 gst_gl_shader_use (src->shader);
1101 gst_gl_shader_set_uniform_1f (src->shader, "aspect_ratio",
1102 (gfloat) GST_VIDEO_INFO_WIDTH (v_info) /
1103 (gfloat) GST_VIDEO_INFO_HEIGHT (v_info));
1104 gst_gl_context_clear_shader (src->base.context);
1106 return _src_shader_init (impl, context, v_info);
1110 _src_circular_free (gpointer impl)
1112 struct SrcShader *src = impl;
1117 _src_shader_deinit (impl);
1123 _src_circular_new (GstGLTestSrc * test)
1125 struct SrcShader *src = g_new0 (struct SrcShader, 1);
1127 src->base.src = test;
1132 static const struct SrcFuncs src_circular = {
1133 GST_GL_TEST_SRC_CIRCULAR,
1136 _src_mandelbrot_fill_bound_fbo,
1140 static const struct SrcFuncs *src_impls[] = {
1157 const struct SrcFuncs *
1158 gst_gl_test_src_get_src_funcs_for_pattern (GstGLTestSrcPattern pattern)
1162 for (i = 0; i < G_N_ELEMENTS (src_impls); i++) {
1163 if (src_impls[i]->pattern == pattern)
1164 return src_impls[i];