Merge lp:~ahmed-a-ammar/pigment/pigment-gles2 into lp:~loic.molinari/pigment/trunk
- pigment-gles2
- Merge into trunk
Proposed by
Ahmed Ammar
Status: | Needs review |
---|---|
Proposed branch: | lp:~ahmed-a-ammar/pigment/pigment-gles2 |
Merge into: | lp:~loic.molinari/pigment/trunk |
Diff against target: |
1362 lines (+1077/-25) 9 files modified
ChangeLog (+15/-0) configure.ac (+48/-3) src/pgm/gst/pgm-gst-image.c (+77/-13) src/renderers/opengles/Makefile.am (+49/-1) src/renderers/opengles/backend-native.c (+22/-1) src/renderers/opengles/backend-x11.c (+26/-5) src/renderers/opengles/plugin-opengles2.c (+838/-0) tests/manual/test-geometry-sorting.c (+1/-1) tests/manual/test-gst-image.c (+1/-1) |
To merge this branch: | bzr merge lp:~ahmed-a-ammar/pigment/pigment-gles2 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Loïc Molinari | Pending | ||
Review via email: mp+25630@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Unmerged revisions
- 255. By Ahmed Ammar
-
* configure.ac:
* src/pgm/gst/pgm- gst-image. c:
* src/renderers/opengles/ Makefile. am:
* src/renderers/opengles/ backend- native. c:
* src/renderers/opengles/ backend- x11.c:
* src/renderers/opengles/ plugin- opengles2. c:
Implementation for OpenGL ES 2 renderer. Currently supports three texture
units and no lights.* tests/manual/
test-geometry- sorting. c:
* tests/manual/test-gst- image.c:
Modified tests to use auto renderer selection.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'ChangeLog' |
2 | --- ChangeLog 2010-05-19 16:53:41 +0000 |
3 | +++ ChangeLog 2010-05-19 17:34:31 +0000 |
4 | @@ -1,3 +1,18 @@ |
5 | +2010-05-19 Ahmed Ammar <ahmed.ammar@connectmetv.com> |
6 | + |
7 | + * configure.ac: |
8 | + * src/pgm/gst/pgm-gst-image.c: |
9 | + * src/renderers/opengles/Makefile.am: |
10 | + * src/renderers/opengles/backend-native.c: |
11 | + * src/renderers/opengles/backend-x11.c: |
12 | + * src/renderers/opengles/plugin-opengles2.c: |
13 | + Implementation for OpenGL ES 2 renderer. Currently supports three texture |
14 | + units and no lights. |
15 | + |
16 | + * tests/manual/test-geometry-sorting.c: |
17 | + * tests/manual/test-gst-image.c: |
18 | + Modified tests to use auto renderer selection. |
19 | + |
20 | 2010-05-19 Loïc Molinari <loic@fluendo.com> |
21 | |
22 | Patch by: Ahmed Ammar <ahmed.ammar@connectmetv.com> |
23 | |
24 | === modified file 'configure.ac' |
25 | --- configure.ac 2010-05-10 10:09:50 +0000 |
26 | +++ configure.ac 2010-05-19 17:34:31 +0000 |
27 | @@ -247,6 +247,8 @@ |
28 | |
29 | AC_CHECK_HEADERS([GLES/egl.h], [HAVE_EGL=yes], [HAVE_EGL=no]) |
30 | AC_CHECK_HEADERS([GLES/gl.h], [HAVE_GLES=yes], [HAVE_GLES=no]) |
31 | +AC_CHECK_HEADERS([GLES2/gl2.h], [HAVE_GLES2=yes], [HAVE_GLES2=no]) |
32 | +AC_CHECK_HEADERS([EGL/egl.h], [HAVE_EGL2=yes], [HAVE_EGL2=no]) |
33 | |
34 | AC_ARG_ENABLE(opengles1-gdl, |
35 | AS_HELP_STRING([--enable-opengles1-gdl],[enable build of OpenGL ES 1 renderer using Intel GDL backend]), |
36 | @@ -270,6 +272,38 @@ |
37 | ], |
38 | [ENABLE_OPENGLES1_X11=no]) |
39 | |
40 | +AC_ARG_ENABLE(opengles2-x11, |
41 | + AC_HELP_STRING([--enable-opengles2-x11], [enable build of OpenGL ES 2 renderer using X11 backend]), |
42 | + [ |
43 | + case "${enableval}" in |
44 | + yes) ENABLE_OPENGLES2_X11=yes ;; |
45 | + no) ENABLE_OPENGLES2_X11=no ;; |
46 | + *) AC_MSG_ERROR(bad value ${enableval} for --enable-opengles2-x11) ;; |
47 | + esac |
48 | + ], |
49 | + [ENABLE_OPENGLES2_X11=no]) |
50 | + |
51 | +if test x$HAVE_EGL2 = xyes -a x$HAVE_GLES2 = xyes; then |
52 | + if test x$ENABLE_OPENGLES2_X11 = xyes -a x$HAVE_X11 = xyes; then |
53 | + AC_DEFINE([HAVE_EGL2_X11], [1], |
54 | + [Defined to 1 if the OpenGL ES 2 renderer uses the X11 backend]) |
55 | + HAVE_OPENGLES2_PLUGIN="yes" |
56 | + OPENGLES2_BACKEND="(X11 backend)" |
57 | + PGM_GLES2_CFLAGS="$XLIB_CFLAG $GLIB_CFLAGS" |
58 | + PGM_GLES2_LIBS="$XLIB_LIBS $GLIB_LIBS -lGLESv2 -lEGL" |
59 | + else |
60 | + AC_DEFINE([HAVE_EGL2_NATIVE], [1], |
61 | + [Defined to 1 if the OpenGL ES 2 renderer uses the native backend]) |
62 | + HAVE_OPENGLES2_PLUGIN="yes" |
63 | + OPENGLES2_BACKEND="(native backend)" |
64 | + PGM_GLES2_CFLAGS="$GLIB_CFLAGS" |
65 | + PGM_GLES2_LIBS="$GLIB_LIBS -lGLESv2 -lEGL" |
66 | + fi |
67 | +else |
68 | + HAVE_OPENGLES2_PLUGIN="no" |
69 | + OPENGLES2_BACKEND="" |
70 | +fi |
71 | + |
72 | if test x$HAVE_EGL = xyes -a x$HAVE_GLES = xyes; then |
73 | if test x$ENABLE_OPENGLES1_GDL = xyes; then |
74 | AC_CHECK_HEADERS([libgdl.h], [HAVE_GDL=yes], [HAVE_GDL=no]) |
75 | @@ -290,8 +324,8 @@ |
76 | [Defined to 1 if the OpenGL ES 1 renderer uses the X11 backend]) |
77 | HAVE_OPENGLES1_PLUGIN="yes" |
78 | OPENGLES1_BACKEND="(X11 backend)" |
79 | - PGM_GLES1_CFLAGS="$GLIB_CFLAGS" |
80 | - PGM_GLES1_LIBS="$GLIB_LIBS -lGLES_CM" |
81 | + PGM_GLES1_CFLAGS="$XLIB_LIBS $GLIB_CFLAGS" |
82 | + PGM_GLES1_LIBS="$XLIB_LIBS $GLIB_LIBS -lGLES_CM -lEGL" |
83 | else |
84 | HAVE_OPENGLES1_PLUGIN="no" |
85 | OPENGLES1_BACKEND="" |
86 | @@ -302,7 +336,7 @@ |
87 | HAVE_OPENGLES1_PLUGIN="yes" |
88 | OPENGLES1_BACKEND="(native backend)" |
89 | PGM_GLES1_CFLAGS="$GLIB_CFLAGS" |
90 | - PGM_GLES1_LIBS="$GLIB_LIBS -lGLES_CM" |
91 | + PGM_GLES1_LIBS="$GLIB_LIBS -lGLES_CM -lEGL" |
92 | fi |
93 | else |
94 | HAVE_OPENGLES1_PLUGIN="no" |
95 | @@ -313,9 +347,19 @@ |
96 | AC_SUBST(HAVE_OPENGLES1_PLUGIN) |
97 | AC_SUBST(PGM_GLES1_CFLAGS) |
98 | AC_SUBST(PGM_GLES1_LIBS) |
99 | + |
100 | +AC_SUBST(OPENGLES2_BACKEND) |
101 | +AC_SUBST(HAVE_OPENGLES2_PLUGIN) |
102 | +AC_SUBST(PGM_GLES2_CFLAGS) |
103 | +AC_SUBST(PGM_GLES2_LIBS) |
104 | + |
105 | AM_CONDITIONAL(HAVE_OPENGLES1_PLUGIN_COND, test x$HAVE_OPENGLES1_PLUGIN = xyes) |
106 | +AM_CONDITIONAL(HAVE_OPENGLES2_PLUGIN_COND, test x$HAVE_OPENGLES2_PLUGIN = xyes) |
107 | +AM_CONDITIONAL(HAVE_OPENGLES_PLUGIN_COND, test x$HAVE_OPENGLES2_PLUGIN = xyes -o x$HAVE_OPENGLES1_PLUGIN = xyes ) |
108 | AM_CONDITIONAL(HAVE_EGL_GDL_COND, test x$HAVE_EGL = xyes -a x$HAVE_GLES = xyes -a x$ENABLE_OPENGLES1_GDL = xyes) |
109 | AM_CONDITIONAL(HAVE_EGL_X11_COND, test x$HAVE_EGL = xyes -a x$HAVE_GLES = xyes -a x$ENABLE_OPENGLES1_X11 = xyes) |
110 | +AM_CONDITIONAL(HAVE_EGL2_X11_COND, test x$HAVE_EGL2 = xyes -a x$HAVE_GLES2 = xyes -a x$ENABLE_OPENGLES2_X11 = xyes) |
111 | +AM_CONDITIONAL(HAVE_EGL2_NATIVE_COND, test x$HAVE_EGL2 = xyes -a x$HAVE_GLES2 = xyes -a x$ENABLE_OPENGLES2_X11 = xno) |
112 | AM_CONDITIONAL(HAVE_EGL_NATIVE_COND, test x$HAVE_EGL = xyes -a x$HAVE_GLES = xyes -a x$ENABLE_OPENGLES1_X11 = xno -a x$ENABLE_OPENGLES1_GDL = xno) |
113 | |
114 | # *** Documentation *** |
115 | @@ -448,6 +492,7 @@ |
116 | echo " 3D graphics engine: yes" |
117 | echo " OpenGL renderer: ${HAVE_OPENGL_PLUGIN} ${OPENGL_BACKEND}" |
118 | echo " OpenGL ES 1 renderer: ${HAVE_OPENGLES1_PLUGIN} ${OPENGLES1_BACKEND}" |
119 | +echo " OpenGL ES 2 renderer: ${HAVE_OPENGLES2_PLUGIN} ${OPENGLES2_BACKEND}" |
120 | echo " GUI classes: ${HAVE_GUI_CLASSES}" |
121 | echo " GStreamer classes: ${HAVE_GST_CLASSES}" |
122 | echo " GTK+ classes: ${HAVE_GTK_CLASSES}" |
123 | |
124 | === modified file 'src/pgm/gst/pgm-gst-image.c' |
125 | --- src/pgm/gst/pgm-gst-image.c 2009-11-30 18:52:29 +0000 |
126 | +++ src/pgm/gst/pgm-gst-image.c 2010-05-19 17:34:31 +0000 |
127 | @@ -17,6 +17,7 @@ |
128 | * |
129 | * Contributor(s): |
130 | * Loïc Molinari <loic@fluendo.com> |
131 | + * Ahmed Ammar <ahmed.ammar@connecmetv.com> |
132 | */ |
133 | |
134 | /** |
135 | @@ -47,10 +48,12 @@ |
136 | static void pgm_gst_image_map (PgmNode*, PgmRenderer*, gfloat, gfloat); |
137 | static void pgm_gst_image_unmap (PgmNode*); |
138 | |
139 | -/* OpenGL ARB fragment program to convert from YV12/I420 planar YCbCr to RGB |
140 | - * color space using coefficients from the ITU-R BT.601 standard for SDTV and |
141 | - * the equations detailed in the book "Video Demystified, 4th Edition" */ |
142 | -static const gchar *ycbcr2rgb_bt601_fp = |
143 | +/* Shaders converting from YV12/I420 planar YCbCr to RGB color space using |
144 | + * coefficients from the ITU-R BT.601 standard for SDTV and the equations |
145 | + * detailed in the book "Video Demystified, 4th Edition" */ |
146 | + |
147 | +/* OpenGL ARB fragment program */ |
148 | +static const gchar *ycbcr2rgb_bt601_glarbfp = |
149 | "!!ARBfp1.0" |
150 | "OPTION ARB_precision_hint_fastest;" |
151 | "ATTRIB position = fragment.texcoord[0];" |
152 | @@ -65,12 +68,52 @@ |
153 | "MUL result.color, fragment.color, color;" |
154 | "END"; |
155 | |
156 | +/* OpenGL ES 2 shaders */ |
157 | +static const gchar *ycbcr2rgb_bt601_glslesvp = |
158 | + "uniform mat4 pgm_projection;\n" |
159 | + "uniform mat4 pgm_modelview;\n" |
160 | + "attribute highp vec4 pgm_position;\n" |
161 | + "attribute highp vec4 pgm_color;\n" |
162 | + "attribute highp vec4 pgm_texcoord;\n" |
163 | + "varying highp vec2 frag_texcoord;\n" |
164 | + "varying highp vec4 frag_color;\n" |
165 | + "void main() {\n" |
166 | + " frag_texcoord = pgm_texcoord.xy;\n" |
167 | + " frag_color = pgm_color/255.0;\n" |
168 | + " gl_Position = pgm_projection * pgm_modelview * pgm_position;\n" |
169 | + "}\n"; |
170 | +static const gchar *ycbcr2rgb_bt601_glslesfp = |
171 | + "uniform sampler2D pgm_texture0;\n" |
172 | + "uniform sampler2D pgm_texture1;\n" |
173 | + "uniform sampler2D pgm_texture2;\n" |
174 | + "varying highp vec2 frag_texcoord;\n" |
175 | + "varying lowp vec4 frag_color;\n" |
176 | + "void main() {" |
177 | + " const lowp vec4 kcr = vec4( 1.596, -0.813, 0, 0 );\n" |
178 | + " const lowp vec4 kcb = vec4( 0, -0.391, 2.018, 0 );\n" |
179 | + " const lowp vec4 kadj = vec4( -0.871, 0.53, -1.082, 0 );\n" |
180 | + " lowp float y = texture2D(pgm_texture0, frag_texcoord).x;\n" |
181 | + " lowp float cb = texture2D(pgm_texture1, frag_texcoord).x;\n" |
182 | + " lowp float cr = texture2D(pgm_texture2, frag_texcoord).x;\n" |
183 | + " lowp vec4 color = vec4(y * 1.164);\n" |
184 | + " color += kcr * cr;\n" |
185 | + " color += kcb * cb;\n" |
186 | + " color += kadj;\n" |
187 | + " gl_FragColor = vec4(color.r, color.g, color.b, 1.0);\n" |
188 | + "}\n"; |
189 | + |
190 | /* Image negociated format */ |
191 | -typedef enum { |
192 | +enum { |
193 | IMAGE_NOT_NEGOCIATED = 0, |
194 | IMAGE_RGB, |
195 | IMAGE_YCBCR |
196 | -} ImageNegociatedFormat; |
197 | +}; |
198 | + |
199 | +/* Image available shading language */ |
200 | +enum { |
201 | + IMAGE_SHADING_LANGUAGE_ARBP = (1 << 0), |
202 | + IMAGE_SHADING_LANGUAGE_GLSLES = (1 << 1) |
203 | +} ; |
204 | |
205 | /* Private structure */ |
206 | struct _PgmGstImagePimpl { |
207 | @@ -86,6 +129,7 @@ |
208 | gfloat texture_ratio; |
209 | PgmGstImageLayout layout; |
210 | guint8 negociated_format; |
211 | + guint8 shading_language; |
212 | }; |
213 | |
214 | /* GObject type definition */ |
215 | @@ -158,6 +202,7 @@ |
216 | /* pimpl->texture_ratio = 0.0f; */ |
217 | pimpl->layout = PGM_GST_IMAGE_SCALED; |
218 | /* pimpl->negociated_format = 0; */ |
219 | + /* pimpl->shading_language = 0; */ |
220 | } |
221 | |
222 | /* Private functions */ |
223 | @@ -317,11 +362,18 @@ |
224 | pgm_mesh_set_texture (pimpl->mesh, 1, cb); |
225 | pgm_mesh_set_texture (pimpl->mesh, 2, cr); |
226 | |
227 | - /* Since we checked the support for ARB fragment program support for the |
228 | - * mapped renderer in the map virtual function, we can safely apply the |
229 | - * color space conversion shader to the mesh */ |
230 | - shader = pgm_shader_new ("arbp", NULL, 0, NULL, 0, ycbcr2rgb_bt601_fp, |
231 | - strlen (ycbcr2rgb_bt601_fp), 0); |
232 | + /* Since we checked the support for shaders for the mapped renderer in the |
233 | + * map virtual function, we can safely apply the color space conversion |
234 | + * shader to the mesh depending on the supported language */ |
235 | + if (pimpl->shading_language & IMAGE_SHADING_LANGUAGE_ARBP) |
236 | + shader = pgm_shader_new ("arbp", NULL, 0, NULL, 0, |
237 | + ycbcr2rgb_bt601_glarbfp, |
238 | + strlen (ycbcr2rgb_bt601_glarbfp), 0); |
239 | + else |
240 | + shader = pgm_shader_new ("glsles", ycbcr2rgb_bt601_glslesvp, |
241 | + strlen (ycbcr2rgb_bt601_glslesvp), NULL, 0, |
242 | + ycbcr2rgb_bt601_glslesfp, |
243 | + strlen (ycbcr2rgb_bt601_glslesfp), 0); |
244 | pgm_mesh_set_shader (pimpl->mesh, shader); |
245 | |
246 | /* Store the texture ratio, no need to check for a height of 0 since such a |
247 | @@ -410,7 +462,20 @@ |
248 | if (strcmp (sl->language, "arbp") == 0) |
249 | { |
250 | if (sl->programs | PGM_RENDERER_FRAGMENT_PROGRAM) |
251 | - formats |= PGM_GST_BASE_YCBCR; |
252 | + { |
253 | + formats |= PGM_GST_BASE_YCBCR; |
254 | + pimpl->shading_language = IMAGE_SHADING_LANGUAGE_ARBP; |
255 | + } |
256 | + break; |
257 | + } |
258 | + else if (strcmp (sl->language, "glsles") == 0) |
259 | + { |
260 | + if (sl->programs | PGM_RENDERER_FRAGMENT_PROGRAM |
261 | + && sl->programs | PGM_RENDERER_VERTEX_PROGRAM) |
262 | + { |
263 | + formats |= PGM_GST_BASE_YCBCR; |
264 | + pimpl->shading_language = IMAGE_SHADING_LANGUAGE_GLSLES; |
265 | + } |
266 | break; |
267 | } |
268 | walk = walk->next; |
269 | @@ -536,7 +601,6 @@ |
270 | /* Set up the initial average position */ |
271 | pgm_mesh_set_average_position (pimpl->mesh, x + pimpl->width * 0.5f, |
272 | y + pimpl->height * 0.5f, z); |
273 | - |
274 | return PGM_NODE (image); |
275 | } |
276 | |
277 | |
278 | === modified file 'src/renderers/opengles/Makefile.am' |
279 | --- src/renderers/opengles/Makefile.am 2009-11-04 17:50:39 +0000 |
280 | +++ src/renderers/opengles/Makefile.am 2010-05-19 17:34:31 +0000 |
281 | @@ -1,7 +1,18 @@ |
282 | -if HAVE_OPENGLES1_PLUGIN_COND |
283 | +if HAVE_OPENGLES_PLUGIN_COND |
284 | |
285 | plugindir = @PLUGIN_PATH@ |
286 | + |
287 | +if HAVE_OPENGLES1_PLUGIN_COND |
288 | +if HAVE_OPENGLES2_PLUGIN_COND |
289 | +plugin_LTLIBRARIES = libpgmopengles1.la libpgmopengles2.la |
290 | +else |
291 | plugin_LTLIBRARIES = libpgmopengles1.la |
292 | +endif |
293 | +else |
294 | +plugin_LTLIBRARIES = libpgmopengles2.la |
295 | +endif |
296 | + |
297 | +if HAVE_OPENGLES1_PLUGIN_COND |
298 | |
299 | libpgmopengles1_la_DEPENDENCIES = \ |
300 | $(top_builddir)/src/pgm/libpigment-@PGM_MAJORMINOR@.la |
301 | @@ -39,3 +50,40 @@ |
302 | noinst_HEADERS = backend.h |
303 | |
304 | endif |
305 | + |
306 | +if HAVE_OPENGLES2_PLUGIN_COND |
307 | + |
308 | + |
309 | +libpgmopengles2_la_DEPENDENCIES = \ |
310 | + $(top_builddir)/src/pgm/libpigment-@PGM_MAJORMINOR@.la |
311 | + |
312 | +if HAVE_EGL2_NATIVE_COND |
313 | +libpgmopengles2_la_SOURCES = \ |
314 | + plugin-opengles2.c \ |
315 | + backend-native.c |
316 | +endif |
317 | +if HAVE_EGL2_X11_COND |
318 | +libpgmopengles2_la_SOURCES = \ |
319 | + plugin-opengles2.c \ |
320 | + backend-x11.c |
321 | +endif |
322 | + |
323 | +# egl.h contains non-strictly prototyped function declarations |
324 | +libpgmopengles2_la_CFLAGS = \ |
325 | + -I$(top_srcdir)/src -DHAVE_GLES2 \ |
326 | + $(PGM_CFLAGS) -Wno-strict-prototypes \ |
327 | + $(PGM_GLES2_CFLAGS) |
328 | + |
329 | +libpgmopengles2_la_LIBADD = \ |
330 | + $(top_builddir)/src/pgm/libpigment-@PGM_MAJORMINOR@.la \ |
331 | + $(PGM_GLES2_LIBS) |
332 | + |
333 | +libpgmopengles2_la_LDFLAGS = $(PGM_PLUGIN_LDFLAGS) |
334 | + |
335 | +libpgmopengles2_la_LIBTOOLFLAGS = --tag=disable-static |
336 | + |
337 | +noinst_HEADERS = backend.h |
338 | + |
339 | +endif |
340 | + |
341 | +endif |
342 | |
343 | === modified file 'src/renderers/opengles/backend-native.c' |
344 | --- src/renderers/opengles/backend-native.c 2010-05-11 08:42:10 +0000 |
345 | +++ src/renderers/opengles/backend-native.c 2010-05-19 17:34:31 +0000 |
346 | @@ -17,6 +17,7 @@ |
347 | * |
348 | * Contributor(s): |
349 | * Loïc Molinari <loic@fluendo.com> |
350 | + * Ahmed Ammar <ahmed.ammar@connectmetv.com> |
351 | */ |
352 | |
353 | #ifdef HAVE_CONFIG_H |
354 | @@ -24,7 +25,12 @@ |
355 | #endif /* HAVE_CONFIG_H */ |
356 | |
357 | #include "backend.h" |
358 | + |
359 | +#ifdef HAVE_GLES2 |
360 | +#include <EGL/egl.h> |
361 | +#else |
362 | #include <GLES/egl.h> |
363 | +#endif |
364 | |
365 | /* Private structure */ |
366 | typedef struct { |
367 | @@ -87,9 +93,21 @@ |
368 | EGL_GREEN_SIZE, 6, |
369 | EGL_BLUE_SIZE, 5, |
370 | EGL_DEPTH_SIZE, 16, |
371 | +#ifdef HAVE_GLES2 |
372 | + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
373 | +#else |
374 | EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, |
375 | +#endif |
376 | EGL_NONE |
377 | }; |
378 | + |
379 | + const EGLint context_attribs[] = { |
380 | +#ifdef HAVE_GLES2 |
381 | + EGL_CONTEXT_CLIENT_VERSION, 2, |
382 | +#endif |
383 | + EGL_NONE |
384 | + }; |
385 | + |
386 | const gchar *version, *vendor, *extensions; |
387 | BackendNative *native; |
388 | EGLConfig config; |
389 | @@ -106,6 +124,9 @@ |
390 | PGM_ERROR_OBJECT (native->rdr, "can't open default display"); |
391 | return NULL; |
392 | } |
393 | + |
394 | + eglBindAPI(EGL_OPENGL_ES_API); |
395 | + |
396 | if (eglInitialize (native->dpy, NULL, NULL) == EGL_FALSE) |
397 | { |
398 | print_egl_error (native->rdr, "eglInitialize"); |
399 | @@ -142,7 +163,7 @@ |
400 | return NULL; |
401 | } |
402 | native->context = eglCreateContext (native->dpy, config, |
403 | - EGL_NO_CONTEXT, NULL); |
404 | + EGL_NO_CONTEXT, context_attribs); |
405 | if (native->context == EGL_NO_CONTEXT) |
406 | { |
407 | print_egl_error (native->rdr, "eglCreateContext"); |
408 | |
409 | === modified file 'src/renderers/opengles/backend-x11.c' |
410 | --- src/renderers/opengles/backend-x11.c 2010-05-11 08:42:10 +0000 |
411 | +++ src/renderers/opengles/backend-x11.c 2010-05-19 17:34:31 +0000 |
412 | @@ -17,6 +17,7 @@ |
413 | * |
414 | * Contributor(s): |
415 | * Loïc Molinari <loic@fluendo.com> |
416 | + * Ahmed Ammar <ahmed.ammar@connectmetv.com> |
417 | */ |
418 | |
419 | #ifdef HAVE_CONFIG_H |
420 | @@ -25,7 +26,11 @@ |
421 | |
422 | #include "backend.h" |
423 | #include <string.h> /* memset */ |
424 | +#ifdef HAVE_GLES2 |
425 | +#include <EGL/egl.h> |
426 | +#else |
427 | #include <GLES/egl.h> |
428 | +#endif |
429 | #include <X11/Xlib.h> |
430 | #include <X11/Xutil.h> |
431 | #include <X11/Xatom.h> |
432 | @@ -643,8 +648,19 @@ |
433 | EGL_GREEN_SIZE, 8, |
434 | EGL_BLUE_SIZE, 8, |
435 | EGL_DEPTH_SIZE, 0, |
436 | +#ifdef HAVE_GLES2 |
437 | + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
438 | +#endif |
439 | EGL_NONE |
440 | }; |
441 | + |
442 | + const EGLint context_attribs[] = { |
443 | +#ifdef HAVE_GLES2 |
444 | + EGL_CONTEXT_CLIENT_VERSION, 2, |
445 | +#endif |
446 | + EGL_NONE |
447 | + }; |
448 | + |
449 | const gchar *version, *vendor, *extensions; |
450 | BackendX11 *x11; |
451 | EGLConfig config; |
452 | @@ -670,6 +686,9 @@ |
453 | g_slice_free1 (sizeof (BackendX11), x11); |
454 | return NULL; |
455 | } |
456 | + |
457 | + eglBindAPI(EGL_OPENGL_ES_API); |
458 | + |
459 | if (eglInitialize (x11->egldpy, NULL, NULL) == EGL_FALSE) |
460 | { |
461 | print_egl_error (x11->rdr, "eglInitialize"); |
462 | @@ -709,7 +728,8 @@ |
463 | g_slice_free1 (sizeof (BackendX11), x11); |
464 | return NULL; |
465 | } |
466 | - x11->context = eglCreateContext (x11->egldpy, config, EGL_NO_CONTEXT, NULL); |
467 | + x11->context = eglCreateContext (x11->egldpy, config, |
468 | + EGL_NO_CONTEXT, context_attribs); |
469 | if (x11->context == EGL_NO_CONTEXT) |
470 | { |
471 | print_egl_error (x11->rdr, "eglCreateContext"); |
472 | @@ -856,16 +876,17 @@ |
473 | { |
474 | case PGM_RENDERER_LEFT_ARROW: |
475 | XDefineCursor (x11->dpy, x11->win, XCreateFontCursor |
476 | - (x11->dpy, XC_top_left_arrow)); |
477 | + (x11->dpy, XC_left_ptr)); |
478 | break; |
479 | |
480 | case PGM_RENDERER_INHERIT: |
481 | XDefineCursor (x11->dpy, x11->win, XCreateFontCursor |
482 | - (x11->dpy, XC_top_left_arrow)); |
483 | + (x11->dpy, XC_left_ptr)); |
484 | break; |
485 | |
486 | - case PGM_RENDERER_NONE: |
487 | - XDefineCursor (x11->dpy, x11->win, x11->none_cursor); |
488 | + case PGM_RENDERER_FLEUR: |
489 | + XDefineCursor (x11->dpy, x11->win, |
490 | + XCreateFontCursor (x11->dpy, XC_fleur)); |
491 | break; |
492 | |
493 | default: |
494 | |
495 | === added file 'src/renderers/opengles/plugin-opengles2.c' |
496 | --- src/renderers/opengles/plugin-opengles2.c 1970-01-01 00:00:00 +0000 |
497 | +++ src/renderers/opengles/plugin-opengles2.c 2010-05-19 17:34:31 +0000 |
498 | @@ -0,0 +1,838 @@ |
499 | +/* |
500 | + * Pigment 3D graphics engine |
501 | + * Rendering plugin based on OpenGL ES 1 |
502 | + * |
503 | + * Copyright © 2006-2010 Fluendo Embedded S.L. |
504 | + * |
505 | + * This library is free software; you can redistribute it and/or modify it under |
506 | + * the terms of the GNU Lesser General Public License as published by the Free |
507 | + * Software Foundation; either version 2 of the License, or (at your option) any |
508 | + * later version. This library is distributed in the hope that it will be |
509 | + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
510 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser |
511 | + * General Public License for more details. You should have received a copy of |
512 | + * the GNU Lesser General Public License along with this library; if not, write |
513 | + * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
514 | + * MA 02111-1307, USA. |
515 | + * |
516 | + * Contributor(s): |
517 | + * Loïc Molinari <loic@fluendo.com> |
518 | + * Ahmed Ammar <ahmed.ammar@connecmetv.com> |
519 | + */ |
520 | + |
521 | +#ifdef HAVE_CONFIG_H |
522 | +#include "config.h" |
523 | +#endif /* HAVE_CONFIG_H */ |
524 | + |
525 | +#include "backend.h" |
526 | +#include <string.h> /* strlen */ |
527 | +#include <ctype.h> /* isdigit */ |
528 | +#include <stdio.h> |
529 | +#include <stdlib.h> |
530 | +#include <sys/ioctl.h> |
531 | +#include <sys/mman.h> |
532 | +#include <fcntl.h> |
533 | + |
534 | +#define GL_GLEXT_PROTOTYPES |
535 | +#include <GLES2/gl2.h> |
536 | +#include <GLES2/gl2ext.h> |
537 | +#undef GL_GLEXT_PROTOTYPES |
538 | + |
539 | +/* Extension constants */ |
540 | +enum { |
541 | + EXT_BGRA = 0x80e1, |
542 | + EXT_MIRRORED_REPEAT = 0x8370 |
543 | +}; |
544 | + |
545 | +/* Extension flags */ |
546 | +enum { |
547 | + FLAG_TEXTURE_FORMAT_BGRA8888 = (1 << 0) , |
548 | + FLAG_TEXTURE_STREAM = (1 << 1) |
549 | +/* FLAG_BLEND_FUNC_SEPARATE = (1 << 1) */ |
550 | +}; |
551 | + |
552 | +/* OpenGL ES 2 attributes */ |
553 | +enum { |
554 | + PGM_APOSITION = 0, |
555 | + PGM_ACOLOR = 1, |
556 | + PGM_ATEXCOORD = 2, |
557 | +}; |
558 | + |
559 | +/* IMG texture stream structure */ |
560 | +typedef struct { |
561 | + int number; |
562 | + int width; |
563 | + int height; |
564 | + int format; |
565 | +} PluginOpengles2TextureBuffer; |
566 | + |
567 | +/* OpenGL ES 2 vertex shader */ |
568 | +static const gchar *default_glslesvp = |
569 | + "uniform mat4 pgm_projection;\n" |
570 | + "uniform mat4 pgm_modelview;\n" |
571 | + "attribute highp vec4 pgm_position;\n" |
572 | + "attribute mediump vec4 pgm_color;\n" |
573 | + "attribute mediump vec4 pgm_texcoord;\n" |
574 | + "varying mediump vec2 frag_texcoord;\n" |
575 | + "varying mediump vec4 frag_color;\n" |
576 | + "void main() {\n" |
577 | + " frag_texcoord = pgm_texcoord.xy;\n" |
578 | + " frag_color = pgm_color/255.0;\n" |
579 | + " gl_Position = pgm_projection * pgm_modelview * pgm_position;\n" |
580 | + "}\n"; |
581 | +static const gchar *default_glslesfp = |
582 | + "uniform sampler2D pgm_texture0;\n" |
583 | + "varying mediump vec2 frag_texcoord;\n" |
584 | + "varying mediump vec4 frag_color;\n" |
585 | + "void main() {\n" |
586 | + " highp vec4 tex0 = texture2D(pgm_texture0, frag_texcoord);\n" |
587 | + " gl_FragColor.rgb = frag_color.rgb + tex0.rgb;\n" |
588 | + " gl_FragColor.a = frag_color.a * tex0.a;\n" |
589 | + "}\n"; |
590 | + |
591 | +/* Wrapper for the opaque PgmPluginTexture pointer */ |
592 | +typedef struct { |
593 | + GLenum type; |
594 | + GLenum format; |
595 | + GLuint id; |
596 | + gfloat sx; |
597 | + gfloat sy; |
598 | + guint16 width; |
599 | + guint16 height; |
600 | + guint16 miplevels; |
601 | +} PluginOpengles2Texture; |
602 | + |
603 | +/* Wrapper for the opaque PgmPluginShader type */ |
604 | +typedef struct { |
605 | + GLuint vert_index, frag_index, prog_index; |
606 | + GLint proj_index, modelview_index; |
607 | + GLint texture0_index, texture1_index, texture2_index; |
608 | +} PluginOpengles2Shader; |
609 | + |
610 | +/* IMG texture stream functions */ |
611 | +typedef void (*glGetTexAttrFunc) (GLenum target, GLenum pname, GLint *params); |
612 | +typedef void (*glTexBindStreamFunc) (GLint device, GLint deviceoffset); |
613 | +typedef const GLubyte *(*glGetTexDeviceFunc) (GLenum target); |
614 | + |
615 | +/* Extension functions */ |
616 | +typedef struct { |
617 | + /* IMG texture stream functions */ |
618 | + glTexBindStreamFunc glTexBindStreamIMG; |
619 | + glGetTexAttrFunc glGetTexAttrIMG; |
620 | + glGetTexDeviceFunc glGetTexDeviceIMG; |
621 | +} Opengles2ExtensionFunctions; |
622 | + |
623 | +/* Wrapper for the opaque PgmPlugin pointer */ |
624 | +typedef struct { |
625 | + PgmPluginFuncs *funcs; |
626 | + PgmRendererCapabilities *caps; |
627 | + PluginOpengles2Texture *default_texture; |
628 | + PgmRenderer *rdr; |
629 | + Backend *backend; |
630 | + PluginOpengles2Texture *texture; |
631 | + gint32 max_texture_units; |
632 | + guint8 extension_flags; |
633 | + /* GLES2 shader variables */ |
634 | + PluginOpengles2Shader *shader; |
635 | + GLfloat *proj_mat, *modelview_mat; |
636 | +} PluginOpengles2; |
637 | + |
638 | +/* Texture target look-up table */ |
639 | +static const GLenum texture_target[] = { |
640 | + GL_TEXTURE_2D, /* PGM_TEXTURE_2D */ |
641 | + 0 /* PGM_TEXTURE_CUBE */ /* Not supported */ |
642 | +}; |
643 | + |
644 | +/* Texture format look-up table */ |
645 | +static const GLenum texture_format[] = { |
646 | + GL_LUMINANCE, /* PGM_TEXTURE_L8 */ |
647 | + GL_LUMINANCE_ALPHA, /* PGM_TEXTURE_L8A8 */ |
648 | + GL_RGB, /* PGM_TEXTURE_R8G8B8 */ |
649 | + GL_RGB, /* PGM_TEXTURE_B8G8R8 */ /* Not supported */ |
650 | + GL_RGBA, /* PGM_TEXTURE_R8G8B8A8 */ |
651 | + GL_RGBA /* PGM_TEXTURE_B8G8R8A8 */ /* Not supported */ |
652 | +}; |
653 | + |
654 | +/* Plugin functions */ |
655 | +static void |
656 | +set_sync_to_vblank (PluginOpengles2 *plugin, |
657 | + gboolean sync) |
658 | +{ |
659 | + backend_set_sync_to_vblank (plugin->backend, sync); |
660 | +} |
661 | + |
662 | +static void |
663 | +wait_for_vblank (PluginOpengles2 *plugin) |
664 | +{ |
665 | + backend_wait_for_vblank (plugin->backend); |
666 | +} |
667 | + |
668 | +static void |
669 | +clear_buffers (PluginOpengles2 *plugin, |
670 | + PgmPluginClearBuffer flags) |
671 | +{ |
672 | + /* Stencil buffer's not used in Pigment, but graphics hardware stores depth |
673 | + * and stencil information in the same buffer so for best performance it's |
674 | + * recommended that both depth and stencil be cleared together. As a side |
675 | + * note, in the old times filling pixels was expensive and avoided as best |
676 | + * as possible using convoluted tricks, nowadays this is not true anymore. |
677 | + * Modern cards now support buffer compression and fast clearing of buffers |
678 | + * using a constant color. More informations can be found in GPU |
679 | + * manufacturer's architecture and performance papers. */ |
680 | + |
681 | + /* FIXME: Is that valid for embedded GPUs? */ |
682 | + |
683 | + const GLbitfield mask[] = { |
684 | + 0, |
685 | + GL_COLOR_BUFFER_BIT, |
686 | + GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, |
687 | + GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT |
688 | + }; |
689 | + glClear (mask[flags]); |
690 | +} |
691 | + |
692 | +static void |
693 | +set_clear_color (PluginOpengles2 *plugin, |
694 | + PgmVec4 *color) |
695 | +{ |
696 | + glClearColor (color->v[0], color->v[1], color->v[2], color->v[3]); |
697 | +} |
698 | + |
699 | +static void |
700 | +set_viewport (PluginOpengles2 *plugin, |
701 | + gint32 x, |
702 | + gint32 y, |
703 | + gint32 width, |
704 | + gint32 height) |
705 | +{ |
706 | + glViewport (x, y, width, height); |
707 | +} |
708 | + |
709 | +static void |
710 | +set_projection_matrix (PluginOpengles2 *plugin, |
711 | + PgmMat4x4 *matrix) |
712 | +{ |
713 | + const GLfloat transpose[16] = { |
714 | + matrix->m[0], matrix->m[4], matrix->m[8], matrix->m[12], |
715 | + matrix->m[1], matrix->m[5], matrix->m[9], matrix->m[13], |
716 | + matrix->m[2], matrix->m[6], matrix->m[10], matrix->m[14], |
717 | + matrix->m[3], matrix->m[7], matrix->m[11], matrix->m[15] |
718 | + }; |
719 | + |
720 | + memcpy(plugin->proj_mat, transpose, 16*sizeof(GLfloat)); |
721 | + glUniformMatrix4fv(plugin->shader->proj_index, 1, GL_FALSE, plugin->proj_mat); |
722 | +} |
723 | + |
724 | +static void |
725 | +set_modelview_matrix (PluginOpengles2 *plugin, |
726 | + PgmMat4x4 *matrix) |
727 | +{ |
728 | + const GLfloat transpose[16] = { |
729 | + matrix->m[0], matrix->m[4], matrix->m[8], matrix->m[12], |
730 | + matrix->m[1], matrix->m[5], matrix->m[9], matrix->m[13], |
731 | + matrix->m[2], matrix->m[6], matrix->m[10], matrix->m[14], |
732 | + matrix->m[3], matrix->m[7], matrix->m[11], matrix->m[15] |
733 | + }; |
734 | + |
735 | + memcpy(plugin->modelview_mat, transpose, 16*sizeof(GLfloat)); |
736 | + glUniformMatrix4fv(plugin->shader->modelview_index, 1, GL_FALSE, plugin->modelview_mat); |
737 | +} |
738 | + |
739 | +static void |
740 | +draw_primitive (PluginOpengles2 *plugin, |
741 | + gpointer positions, |
742 | + PgmVertexBufferType position_type, |
743 | + guint8 position_size, |
744 | + gpointer colors, |
745 | + PgmVertexBufferType color_type, |
746 | + gpointer texcoords, |
747 | + PgmVertexBufferType texcoord_type, |
748 | + guint8 texcoord_size, |
749 | + guint16 *indices, |
750 | + PgmMeshPrimitiveType primitive_type, |
751 | + guint16 index_count) |
752 | +{ |
753 | + static const GLenum type[] = { |
754 | + 0, /* PGM_VERTEX_BUFFER_NONE */ |
755 | + GL_BYTE, /* PGM_VERTEX_BUFFER_INT8 */ |
756 | + GL_UNSIGNED_BYTE, /* PGM_VERTEX_BUFFER_UINT8 */ |
757 | + GL_SHORT, /* PGM_VERTEX_BUFFER_INT16 */ |
758 | + GL_UNSIGNED_SHORT, /* PGM_VERTEX_BUFFER_UINT16 */ |
759 | + 0, /* PGM_VERTEX_BUFFER_INT32 */ |
760 | + 0, /* PGM_VERTEX_BUFFER_UINT32 */ |
761 | + GL_FLOAT /* PGM_VERTEX_BUFFER_FLOAT */ |
762 | + }; |
763 | + static const GLenum mode[] = { |
764 | + GL_LINES, /* PGM_MESH_LINE_LIST */ |
765 | + GL_LINE_STRIP, /* PGM_MESH_LINE_STRIP */ |
766 | + GL_TRIANGLES, /* PGM_MESH_TRIANGLE_LIST */ |
767 | + GL_TRIANGLE_STRIP /* PGM_MESH_TRIANGLE_STRIP */ |
768 | + }; |
769 | + |
770 | + glVertexAttribPointer(PGM_APOSITION, position_size, type[position_type], GL_FALSE, 0, positions); |
771 | + if (texcoord_type == PGM_VERTEX_BUFFER_NONE) { |
772 | + glEnableVertexAttribArray(PGM_ACOLOR); |
773 | + glVertexAttribPointer(PGM_ACOLOR, 4, type[color_type], GL_FALSE, 0, colors); |
774 | + glDrawElements (mode[primitive_type], index_count, GL_UNSIGNED_SHORT, indices); |
775 | + glDisableVertexAttribArray(PGM_ACOLOR); |
776 | + } else { |
777 | + glEnableVertexAttribArray(PGM_ATEXCOORD); |
778 | + glVertexAttribPointer(PGM_ATEXCOORD, texcoord_size, type[texcoord_type], GL_FALSE, 0, texcoords); |
779 | + glDrawElements (mode[primitive_type], index_count, GL_UNSIGNED_SHORT, indices); |
780 | + glDisableVertexAttribArray(PGM_ATEXCOORD); |
781 | + } |
782 | +} |
783 | + |
784 | +static PgmPluginTexture |
785 | +create_texture (PluginOpengles2 *plugin, |
786 | + PgmTextureTarget target, |
787 | + PgmTextureFormat format, |
788 | + guint16 width, |
789 | + guint16 height) |
790 | +{ |
791 | + PluginOpengles2Texture *texture = g_slice_new (PluginOpengles2Texture); |
792 | + |
793 | + texture->type = texture_target[target]; |
794 | + texture->format = texture_format[format]; |
795 | + texture->width = width; |
796 | + texture->height = height; |
797 | + texture->miplevels = 0; |
798 | + |
799 | + glGenTextures (1, &texture->id); |
800 | + |
801 | + return (PgmPluginTexture) texture; |
802 | +} |
803 | + |
804 | +static void |
805 | +delete_textures (PluginOpengles2 *plugin, |
806 | + PluginOpengles2Texture **textures, |
807 | + guint16 count) |
808 | +{ |
809 | + guint32 i; |
810 | + |
811 | + for (i = 0; i < count; i++) |
812 | + { |
813 | + glDeleteTextures (1, &textures[i]->id); |
814 | + g_slice_free (PluginOpengles2Texture, textures[i]); |
815 | + } |
816 | +} |
817 | + |
818 | +static void |
819 | +bind_texture (PluginOpengles2 *plugin, |
820 | + guint8 unit, |
821 | + PluginOpengles2Texture *texture) |
822 | +{ |
823 | + if (unit < plugin->max_texture_units) |
824 | + { |
825 | + glActiveTexture (GL_TEXTURE0 + unit); |
826 | + if (texture != NULL) |
827 | + glBindTexture (texture->type, texture->id); |
828 | + else |
829 | + glBindTexture (GL_TEXTURE_2D, 0); |
830 | + plugin->texture = texture; |
831 | + } |
832 | + else |
833 | + { |
834 | + PGM_WARN_OBJECT (plugin->rdr, "texture unit %d not available on " |
835 | + "that OpenGL ES 2 implementation", unit); |
836 | + } |
837 | +} |
838 | + |
839 | +static void |
840 | +upload_texture (PluginOpengles2 *plugin, |
841 | + guint16 miplevel, |
842 | + guint16 x_offset, |
843 | + guint16 y_offset, |
844 | + guint16 width, |
845 | + guint16 height, |
846 | + gpointer texels) |
847 | +{ |
848 | + PluginOpengles2Texture *tex = plugin->texture; |
849 | + |
850 | + static int idx = 0; |
851 | + if (tex->miplevels & (1 << miplevel)) |
852 | + { |
853 | + glTexSubImage2D (tex->type, miplevel, x_offset, y_offset, width, |
854 | + height, tex->format, GL_UNSIGNED_BYTE, texels); |
855 | + } |
856 | + else |
857 | + { |
858 | + glTexImage2D (tex->type, miplevel, tex->format, tex->width, tex->height, |
859 | + 0, tex->format, GL_UNSIGNED_BYTE, NULL); |
860 | + glTexSubImage2D (tex->type, miplevel, x_offset, y_offset, width, height, |
861 | + tex->format, GL_UNSIGNED_BYTE, texels); |
862 | + tex->miplevels |= 1 << miplevel; |
863 | + } |
864 | + } |
865 | + |
866 | +static void |
867 | +set_texture_states (PluginOpengles2 *plugin, |
868 | + PgmTextureFilter min_filter, |
869 | + PgmTextureFilter mag_filter, |
870 | + PgmTextureFilter mip_filter, |
871 | + PgmTextureWrapping wrap_u, |
872 | + PgmTextureWrapping wrap_v) |
873 | +{ |
874 | + static const GLenum map[] = { |
875 | + 0, /* PGM_TEXTURE_NONE */ |
876 | + GL_NEAREST, /* PGM_TEXTURE_NEAREST */ |
877 | + GL_LINEAR, /* PGM_TEXTURE_LINEAR */ |
878 | + GL_NEAREST_MIPMAP_NEAREST, |
879 | + GL_LINEAR_MIPMAP_NEAREST, |
880 | + GL_NEAREST_MIPMAP_LINEAR, |
881 | + GL_LINEAR_MIPMAP_LINEAR |
882 | + }; |
883 | + static const GLenum wrap[] = { |
884 | + GL_CLAMP_TO_EDGE, /* PGM_PLUGIN_CLAMP */ |
885 | + GL_CLAMP_TO_EDGE, /* PGM_PLUGIN_BORDER */ |
886 | + GL_REPEAT, /* PGM_PLUGIN_REPEAT */ |
887 | + EXT_MIRRORED_REPEAT /* PGM_PLUGIN_MIRROR */ |
888 | + }; |
889 | + const GLenum type = plugin->texture->type; |
890 | + glTexParameteri (type, GL_TEXTURE_MIN_FILTER, map[min_filter+mip_filter*2]); |
891 | + glTexParameteri (type, GL_TEXTURE_MAG_FILTER, map[mag_filter]); |
892 | + glTexParameteri (type, GL_TEXTURE_WRAP_S, wrap[wrap_u]); |
893 | + glTexParameteri (type, GL_TEXTURE_WRAP_T, wrap[wrap_v]); |
894 | +} |
895 | + |
896 | +static PgmPluginShader |
897 | +create_shader (PluginOpengles2 *plugin, |
898 | + const gchar *language, |
899 | + gpointer vertex_program, |
900 | + gsize vertex_program_size, |
901 | + gpointer geometry_program, |
902 | + gsize geometry_program_size, |
903 | + gpointer fragment_program, |
904 | + gsize fragment_program_size, |
905 | + PgmShaderUniformInfo *uniforms_info, |
906 | + guint8 uniforms_count) |
907 | +{ |
908 | + PluginOpengles2Shader *shader; |
909 | + gint error_position = 0; |
910 | + GLint success; |
911 | + |
912 | + /* XXX Check language validity */ |
913 | + |
914 | + shader = g_slice_new (PluginOpengles2Shader); |
915 | + |
916 | + shader->prog_index = glCreateProgram(); |
917 | + |
918 | + if ((vertex_program != NULL) || (fragment_program != NULL)) |
919 | + { |
920 | + if (vertex_program != NULL) |
921 | + { |
922 | + PGM_INFO_OBJECT(plugin->rdr, "%s: creating new vertex shader\n", __func__); |
923 | + shader->vert_index = glCreateShader(GL_VERTEX_SHADER); |
924 | + glShaderSource(shader->vert_index, 1, (const char**) &vertex_program, (GLint *) &vertex_program_size); |
925 | + glCompileShader(shader->vert_index); |
926 | + glGetShaderiv(shader->vert_index, GL_COMPILE_STATUS, &success); |
927 | + if (!success) PGM_WARN_OBJECT (plugin->rdr, "%s: vertex shader compilation error\n", __func__); |
928 | + else glAttachShader(shader->prog_index, shader->vert_index); |
929 | + } |
930 | + |
931 | + if (fragment_program != NULL) |
932 | + { |
933 | + PGM_INFO_OBJECT(plugin->rdr, "%s: creating new fragment shader\n", __func__); |
934 | + shader->frag_index = glCreateShader(GL_FRAGMENT_SHADER); |
935 | + glShaderSource(shader->frag_index, 1, (const char**) &fragment_program, (GLint *) &fragment_program_size); |
936 | + glCompileShader(shader->frag_index); |
937 | + glGetShaderiv(shader->frag_index, GL_COMPILE_STATUS, &success); |
938 | + if (!success) PGM_WARN_OBJECT (plugin->rdr, "%s: fragment shader compilation error\n", __func__); |
939 | + else glAttachShader(shader->prog_index, shader->frag_index); |
940 | + } |
941 | + |
942 | + /* Bind attributes */ |
943 | + glBindAttribLocation(shader->prog_index, PGM_APOSITION, "pgm_position"); |
944 | + glBindAttribLocation(shader->prog_index, PGM_ACOLOR, "pgm_color"); |
945 | + glBindAttribLocation(shader->prog_index, PGM_ATEXCOORD, "pgm_texcoord"); |
946 | + |
947 | + glLinkProgram(shader->prog_index); |
948 | + glGetProgramiv(shader->prog_index, GL_LINK_STATUS, &success); |
949 | + if (success) |
950 | + { |
951 | + glUseProgram(shader->prog_index); |
952 | + /* Get uniform locations */ |
953 | + shader->proj_index = glGetUniformLocation(shader->prog_index, "pgm_projection"); |
954 | + shader->modelview_index = glGetUniformLocation(shader->prog_index, "pgm_modelview"); |
955 | + |
956 | + shader->texture0_index = glGetUniformLocation(shader->prog_index,"pgm_texture0"); |
957 | + glUniform1i(shader->texture0_index, 0); |
958 | + shader->texture1_index = glGetUniformLocation(shader->prog_index,"pgm_texture1"); |
959 | + glUniform1i(shader->texture1_index, 1); |
960 | + shader->texture2_index = glGetUniformLocation(shader->prog_index,"pgm_texture2"); |
961 | + glUniform1i(shader->texture2_index, 2); |
962 | + } |
963 | + else |
964 | + PGM_WARN_OBJECT (plugin->rdr, "program linking error\n"); |
965 | + } |
966 | + return (PgmPluginShader) shader; |
967 | +} |
968 | + |
969 | +static void |
970 | +delete_shaders (PluginOpengles2 *plugin, |
971 | + PluginOpengles2Shader *shaders, |
972 | + guint16 count) |
973 | +{ |
974 | + guint32 i; |
975 | + for (i = 0; i < count; i++) |
976 | + { |
977 | + glDetachShader(shaders[i].prog_index, shaders[i].vert_index); |
978 | + glDetachShader(shaders[i].prog_index, shaders[i].frag_index); |
979 | + glDeleteProgram(shaders[i].prog_index); |
980 | + g_slice_free (PluginOpengles2Shader, &(shaders[i])); |
981 | + } |
982 | + |
983 | +} |
984 | + |
985 | +static void |
986 | +bind_shader (PluginOpengles2 *plugin, |
987 | + PluginOpengles2Shader *shader) |
988 | +{ |
989 | + GLint success; |
990 | + |
991 | + if (shader != NULL) { |
992 | + glUseProgram(shader->prog_index); |
993 | + glUniformMatrix4fv(plugin->shader->proj_index, 1, GL_FALSE, plugin->proj_mat); |
994 | + glUniformMatrix4fv(plugin->shader->modelview_index, 1, GL_FALSE, plugin->modelview_mat); |
995 | + } |
996 | + plugin->shader = shader; |
997 | +} |
998 | + |
999 | +static void |
1000 | +set_shader_uniforms (PluginOpengles2 *plugin, |
1001 | + PgmShaderUniformData *uniforms) |
1002 | +{ |
1003 | + /* Not used, we have some predefined uniforms, have a look at the default shaders */ |
1004 | + PGM_INFO_OBJECT(plugin->rdr, "%s: set shader uniforms\n", __func__); |
1005 | +} |
1006 | + |
1007 | +static void |
1008 | +swap_buffers (PluginOpengles2 *plugin) |
1009 | +{ |
1010 | + backend_swap_buffers (plugin->backend); |
1011 | +} |
1012 | + |
1013 | +static void |
1014 | +get_screen_size (PluginOpengles2 *plugin, |
1015 | + guint32 *width, |
1016 | + guint32 *height) |
1017 | +{ |
1018 | + backend_get_screen_size (plugin->backend, width, height); |
1019 | +} |
1020 | + |
1021 | +static void |
1022 | +get_screen_resolution (PluginOpengles2 *plugin, |
1023 | + guint32 *width, |
1024 | + guint32 *height) |
1025 | +{ |
1026 | + backend_get_screen_resolution (plugin->backend, width, height); |
1027 | +} |
1028 | + |
1029 | +static void |
1030 | +set_window_title (PluginOpengles2 *plugin, |
1031 | + const gchar *title) |
1032 | +{ |
1033 | + backend_set_window_title (plugin->backend, title); |
1034 | +} |
1035 | + |
1036 | +static void |
1037 | +set_window_visible (PluginOpengles2 *plugin, |
1038 | + gboolean visible) |
1039 | +{ |
1040 | + backend_set_window_visible (plugin->backend, visible); |
1041 | +} |
1042 | + |
1043 | +static void |
1044 | +set_window_decorated (PluginOpengles2 *plugin, |
1045 | + gboolean decorated) |
1046 | +{ |
1047 | + backend_set_window_decorated (plugin->backend, decorated); |
1048 | +} |
1049 | + |
1050 | +static void |
1051 | +set_window_fullscreen (PluginOpengles2 *plugin, |
1052 | + gboolean fullscreen) |
1053 | +{ |
1054 | + backend_set_window_fullscreen (plugin->backend, fullscreen); |
1055 | +} |
1056 | + |
1057 | +static void |
1058 | +set_window_iconified (PluginOpengles2 *plugin, |
1059 | + gboolean iconified) |
1060 | +{ |
1061 | + backend_set_window_iconified (plugin->backend, iconified); |
1062 | +} |
1063 | + |
1064 | +static void |
1065 | +set_window_cursor (PluginOpengles2 *plugin, |
1066 | + PgmRendererCursor cursor) |
1067 | +{ |
1068 | + backend_set_window_cursor (plugin->backend, cursor); |
1069 | +} |
1070 | + |
1071 | +/* static void */ |
1072 | +/* set_window_icon (PluginOpengles2 *plugin, */ |
1073 | +/* GdkPixbuf *icon) */ |
1074 | +/* { */ |
1075 | +/* backend_set_window_icon (plugin->backend, icon); */ |
1076 | +/* } */ |
1077 | + |
1078 | +static void |
1079 | +set_window_size (PluginOpengles2 *plugin, |
1080 | + guint32 width, |
1081 | + guint32 height) |
1082 | +{ |
1083 | + backend_set_window_size (plugin->backend, width, height); |
1084 | +} |
1085 | + |
1086 | +static void |
1087 | +set_window_message_filter (PluginOpengles2 *plugin, |
1088 | + GList *filter) |
1089 | +{ |
1090 | + backend_set_window_message_filter (plugin->backend, filter); |
1091 | +} |
1092 | + |
1093 | +static void |
1094 | +window_focus (PluginOpengles2 *plugin) |
1095 | +{ |
1096 | + backend_window_focus (plugin->backend); |
1097 | +} |
1098 | + |
1099 | +static guint32 |
1100 | +get_window_id (PluginOpengles2 *plugin) |
1101 | +{ |
1102 | + return backend_get_window_id (plugin->backend); |
1103 | +} |
1104 | + |
1105 | +static void |
1106 | +set_window_drag_status (PluginOpengles2 *plugin, |
1107 | + gboolean accept) |
1108 | +{ |
1109 | + backend_set_window_drag_status (plugin->backend, accept); |
1110 | +} |
1111 | + |
1112 | +/* Plugin */ |
1113 | + |
1114 | +static gboolean |
1115 | +is_extension_supported (const gchar *extensions, |
1116 | + const gchar *extension) |
1117 | +{ |
1118 | + if (extensions != NULL && extension != NULL) |
1119 | + { |
1120 | + const gsize len = strlen (extension); |
1121 | + gchar *p = (gchar*) extensions; |
1122 | + gchar *end = p + strlen (p); |
1123 | + |
1124 | + while (p < end) |
1125 | + { |
1126 | + const gsize size = strcspn (p, " "); |
1127 | + if (len == size && strncmp (extension, p, size) == 0) |
1128 | + return TRUE; |
1129 | + p += size + 1; |
1130 | + } |
1131 | + } |
1132 | + |
1133 | + return FALSE; |
1134 | +} |
1135 | + |
1136 | +static gboolean |
1137 | +init_plugin (PluginOpengles2 *plugin, |
1138 | + guint32 options) |
1139 | +{ |
1140 | + const struct { |
1141 | + const gchar *name; guint8 flag; |
1142 | + } extension_map[] = { |
1143 | + { "GL_IMG_texture_format_BGRA8888", FLAG_TEXTURE_FORMAT_BGRA8888 }, |
1144 | + { NULL, 0 } |
1145 | + }; |
1146 | + const gchar *vendor, *renderer, *version, *extensions; |
1147 | + PluginOpengles2Texture *texture; |
1148 | + PgmRendererCapabilities *caps; |
1149 | + PgmPluginFuncs *funcs; |
1150 | + guint8 extension_flags = 0; |
1151 | + guint8 caps_flags = 0; |
1152 | + guint32 i; |
1153 | + |
1154 | + |
1155 | + /* Get the information strings */ |
1156 | + version = (const gchar*) glGetString (GL_VERSION); |
1157 | + vendor = (const gchar*) glGetString (GL_VENDOR); |
1158 | + renderer = (const gchar*) glGetString (GL_RENDERER); |
1159 | + extensions = (const gchar*) glGetString (GL_EXTENSIONS); |
1160 | + PGM_INFO_OBJECT (plugin->rdr, "OpenGL ES vendor: %s", vendor); |
1161 | + PGM_INFO_OBJECT (plugin->rdr, "OpenGL ES renderer: %s", renderer); |
1162 | + PGM_INFO_OBJECT (plugin->rdr, "OpenGL ES version: %s", version); |
1163 | + PGM_DEBUG_OBJECT (plugin->rdr, "OpenGL ES extensions: %s", extensions); |
1164 | + |
1165 | + /* Store the supported extensions in a bitfield */ |
1166 | + for (i = 0; extension_map[i].name != NULL; i++) |
1167 | + if (is_extension_supported (extensions, extension_map[i].name) == TRUE) |
1168 | + extension_flags |= extension_map[i].flag; |
1169 | + plugin->extension_flags = extension_flags; |
1170 | + |
1171 | + /* Set initial states */ |
1172 | + /* XXX: Some of these must be set from the core with dedicated functions */ |
1173 | + glEnableVertexAttribArray(PGM_APOSITION); |
1174 | + glEnable (GL_BLEND); |
1175 | + glDepthFunc (GL_LEQUAL); |
1176 | + glEnable (GL_DEPTH_TEST); |
1177 | + |
1178 | + glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); |
1179 | + glEnable (GL_TEXTURE_2D); |
1180 | + |
1181 | + /* Fill the default texture */ |
1182 | + texture = g_slice_alloc (sizeof (PluginOpengles2Texture)); |
1183 | + texture->type = GL_TEXTURE_2D; |
1184 | + texture->id = 0; |
1185 | + plugin->default_texture = texture; |
1186 | + |
1187 | + /* Allocate memory for modelview/projection matrices */ |
1188 | + plugin->proj_mat = (GLfloat*) malloc (16*sizeof(GLfloat)); |
1189 | + plugin->modelview_mat = (GLfloat*) malloc (16*sizeof(GLfloat)); |
1190 | + |
1191 | + /* Fill the caps */ |
1192 | + caps = pgm_renderer_capabilities_new (); |
1193 | + caps->device_vendor = g_strdup (vendor); |
1194 | + caps->device_description = g_strconcat (renderer, " (", version, ")", NULL); |
1195 | + if (backend_is_window_pluggable (plugin->backend)) |
1196 | + caps_flags |= PGM_RENDERER_PLUGGABLE_WINDOW; |
1197 | + if (backend_is_window_layered (plugin->backend)) |
1198 | + caps_flags |= PGM_RENDERER_LAYERED_WINDOW; |
1199 | + caps->flags = caps_flags; |
1200 | + |
1201 | + /* Store supported shading languages */ |
1202 | + caps->shading_languages = g_list_prepend |
1203 | + (NULL, pgm_renderer_shading_language_new ("glsles", "1.0", PGM_RENDERER_FRAGMENT_PROGRAM | PGM_RENDERER_VERTEX_PROGRAM )); |
1204 | + |
1205 | + /* Store limits */ |
1206 | + glGetIntegerv (GL_MAX_TEXTURE_SIZE, &caps->max_texture_size); |
1207 | + plugin->max_texture_units = caps->max_texture_units = 3; |
1208 | + caps->max_lights = 0; |
1209 | + plugin->caps = caps; |
1210 | + |
1211 | + /* Fill the funcs */ |
1212 | + funcs = g_slice_alloc (sizeof (PgmPluginFuncs)); |
1213 | + funcs->set_sync_to_vblank = |
1214 | + (PgmPluginSetSyncToVBlankFunc) set_sync_to_vblank; |
1215 | + funcs->wait_for_vblank = (PgmPluginWaitForVBlankFunc) wait_for_vblank; |
1216 | + funcs->clear_buffers = (PgmPluginClearBuffersFunc) clear_buffers; |
1217 | + funcs->set_clear_color = (PgmPluginSetClearColorFunc) set_clear_color; |
1218 | + funcs->set_viewport = (PgmPluginSetViewportFunc) set_viewport; |
1219 | + funcs->set_projection_matrix = |
1220 | + (PgmPluginSetProjectionMatrixFunc) set_projection_matrix; |
1221 | + funcs->set_modelview_matrix = |
1222 | + (PgmPluginSetModelviewMatrixFunc) set_modelview_matrix; |
1223 | + funcs->draw_primitive = (PgmPluginDrawPrimitiveFunc) draw_primitive; |
1224 | + funcs->create_texture = (PgmPluginCreateTextureFunc) create_texture; |
1225 | + funcs->delete_textures = (PgmPluginDeleteTexturesFunc) delete_textures; |
1226 | + funcs->bind_texture = (PgmPluginBindTextureFunc) bind_texture; |
1227 | + funcs->upload_texture = (PgmPluginUploadTextureFunc) upload_texture; |
1228 | + funcs->set_texture_states = |
1229 | + (PgmPluginSetTextureStatesFunc) set_texture_states; |
1230 | + funcs->create_shader = (PgmPluginCreateShaderFunc) create_shader; |
1231 | + funcs->delete_shaders = (PgmPluginDeleteShadersFunc) delete_shaders; |
1232 | + funcs->bind_shader = (PgmPluginBindShaderFunc) bind_shader; |
1233 | + funcs->set_shader_uniforms = |
1234 | + (PgmPluginSetShaderUniformsFunc) set_shader_uniforms; |
1235 | + funcs->swap_buffers = (PgmPluginSwapBuffersFunc) swap_buffers; |
1236 | + funcs->get_screen_size = (PgmPluginGetScreenSizeFunc) get_screen_size; |
1237 | + funcs->get_screen_resolution = |
1238 | + (PgmPluginGetScreenResolutionFunc) get_screen_resolution; |
1239 | + funcs->read_pixels = NULL; |
1240 | + funcs->set_window_title = (PgmPluginSetWindowTitleFunc) set_window_title; |
1241 | + funcs->set_window_visible = |
1242 | + (PgmPluginSetWindowVisibleFunc) set_window_visible; |
1243 | + funcs->set_window_decorated = |
1244 | + (PgmPluginSetWindowDecoratedFunc) set_window_decorated; |
1245 | + funcs->set_window_fullscreen = |
1246 | + (PgmPluginSetWindowFullscreenFunc) set_window_fullscreen; |
1247 | + funcs->set_window_iconified = |
1248 | + (PgmPluginSetWindowIconifiedFunc) set_window_iconified; |
1249 | + funcs->set_window_cursor = |
1250 | + (PgmPluginSetWindowCursorFunc) set_window_cursor; |
1251 | +/* funcs->set_window_icon = (PgmPluginSetWindowIconFunc) set_window_icon; */ |
1252 | + funcs->set_window_size = (PgmPluginSetWindowSizeFunc) set_window_size; |
1253 | + funcs->set_window_message_filter = |
1254 | + (PgmPluginSetWindowMessageFilterFunc) set_window_message_filter; |
1255 | + funcs->window_focus = (PgmPluginWindowFocusFunc) window_focus; |
1256 | + funcs->get_window_id = (PgmPluginGetWindowIdFunc) get_window_id; |
1257 | + funcs->set_window_drag_status = |
1258 | + (PgmPluginSetWindowDragStatusFunc) set_window_drag_status; |
1259 | + plugin->funcs = funcs; |
1260 | + |
1261 | + return TRUE; |
1262 | +} |
1263 | + |
1264 | +static PgmPlugin |
1265 | +construct (PgmRenderer *renderer, |
1266 | + GMainContext *context, |
1267 | + guint32 options, |
1268 | + PgmPluginFuncs **funcs, |
1269 | + PgmRendererCapabilities **caps, |
1270 | + PgmPluginTexture *texture, |
1271 | + PgmPluginShader *shader) |
1272 | +{ |
1273 | + PluginOpengles2 *plugin = g_slice_alloc0 (sizeof (PluginOpengles2)); |
1274 | + Backend backend = backend_new (renderer, context, options); |
1275 | + |
1276 | + if (backend != NULL) |
1277 | + { |
1278 | + plugin->rdr = renderer; |
1279 | + plugin->backend = backend; |
1280 | + |
1281 | + plugin->shader = (PluginOpengles2Shader*) create_shader(plugin, "glsles", (gpointer)default_glslesvp, |
1282 | + strlen(default_glslesvp), NULL, 0, |
1283 | + (gpointer) default_glslesfp, |
1284 | + strlen(default_glslesfp), NULL, 0); |
1285 | + |
1286 | + if (init_plugin (plugin, options) == TRUE) |
1287 | + { |
1288 | + *funcs = plugin->funcs; |
1289 | + *caps = plugin->caps; |
1290 | + *texture = plugin->default_texture; |
1291 | + *shader = plugin->shader; |
1292 | + return (PgmPlugin) plugin; |
1293 | + } |
1294 | + else |
1295 | + { |
1296 | + backend_free (backend); |
1297 | + g_slice_free1 (sizeof (PluginOpengles2), plugin); |
1298 | + PGM_ERROR_OBJECT (renderer, "can't initialize OpenGL ES plugin"); |
1299 | + return NULL; |
1300 | + } |
1301 | + } |
1302 | + else |
1303 | + { |
1304 | + PGM_ERROR_OBJECT (renderer, "can't create OpenGL ES context"); |
1305 | + return NULL; |
1306 | + } |
1307 | +} |
1308 | + |
1309 | +static void |
1310 | +destruct (PluginOpengles2 *plugin) |
1311 | +{ |
1312 | + /* XXX destruct shaders? */ |
1313 | + g_slice_free1 (sizeof (PgmPluginFuncs), plugin->funcs); |
1314 | + g_slice_free1 (sizeof (PluginOpengles2Texture), plugin->default_texture); |
1315 | + pgm_renderer_capabilities_free (plugin->caps); |
1316 | + backend_free (plugin->backend); |
1317 | + g_slice_free1 (sizeof (PluginOpengles2), plugin); |
1318 | +} |
1319 | + |
1320 | +#if defined (HAVE_EGL2_NATIVE) |
1321 | +#define description "a plugin based on OpenGL ES 2 (native)" |
1322 | +#elif defined (HAVE_EGL2_X11) |
1323 | +#define description "a plugin based on OpenGL ES 2 (X11)" |
1324 | +#endif |
1325 | + |
1326 | +PGM_PLUGIN_DEFINE ( |
1327 | + "opengles2", /* Name */ |
1328 | + VERSION, /* Version */ |
1329 | + description, /* Description */ |
1330 | + "LGPL", /* License */ |
1331 | + "https://code.fluendo.com/pigment", /* Origin */ |
1332 | + "Ahmed Ammar <ahmed.ammar@connectmetv.com>", /* Author */ |
1333 | + (PgmPluginConstructFunc) construct, /* Constructor */ |
1334 | + (PgmPluginDestructFunc) destruct, /* Destructor */ |
1335 | + PGM_PLUGIN_SECONDARY /* Rank */ |
1336 | +) |
1337 | |
1338 | === modified file 'tests/manual/test-geometry-sorting.c' |
1339 | --- tests/manual/test-geometry-sorting.c 2010-05-07 16:58:25 +0000 |
1340 | +++ tests/manual/test-geometry-sorting.c 2010-05-19 17:34:31 +0000 |
1341 | @@ -447,7 +447,7 @@ |
1342 | pgm_init (&argc, &argv); |
1343 | |
1344 | /* OpenGL renderer creation */ |
1345 | - renderer = pgm_renderer_factory_make ("opengl", 1); |
1346 | + renderer = pgm_renderer_factory_make_auto (); |
1347 | if (!renderer) |
1348 | { |
1349 | g_print ("Cannot create a renderer\n"); |
1350 | |
1351 | === modified file 'tests/manual/test-gst-image.c' |
1352 | --- tests/manual/test-gst-image.c 2010-05-07 16:46:26 +0000 |
1353 | +++ tests/manual/test-gst-image.c 2010-05-19 17:34:31 +0000 |
1354 | @@ -78,7 +78,7 @@ |
1355 | pgm_init (&argc, &argv); |
1356 | gst_init (&argc, &argv); |
1357 | |
1358 | - renderer = pgm_renderer_factory_make ("opengl", 0); |
1359 | + renderer = pgm_renderer_factory_make_auto (); |
1360 | if (!renderer) |
1361 | { |
1362 | g_print ("Cannot create the OpenGL renderer\n"); |