diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index 71cd5974be..0e08495fa4 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -2127,6 +2127,7 @@ tests/evas/evas_test_filters.c \ tests/evas/evas_test_image.c \ tests/evas/evas_test_mesh.c \ tests/evas/evas_test_mask.c \ +tests/evas/evas_test_evasgl.c \ tests/evas/evas_tests_helpers.h \ tests/evas/evas_suite.h diff --git a/src/tests/evas/evas_suite.c b/src/tests/evas/evas_suite.c index 7b087bbaae..242215f65d 100644 --- a/src/tests/evas/evas_suite.c +++ b/src/tests/evas/evas_suite.c @@ -28,6 +28,7 @@ static const Evas_Test_Case etc[] = { { "Images", evas_test_image_object }, { "Meshes", evas_test_mesh }, { "Masking", evas_test_mask }, + { "Evas GL", evas_test_evasgl }, { NULL, NULL } }; diff --git a/src/tests/evas/evas_suite.h b/src/tests/evas/evas_suite.h index 645f758081..574bdc2969 100644 --- a/src/tests/evas/evas_suite.h +++ b/src/tests/evas/evas_suite.h @@ -13,5 +13,6 @@ void evas_test_filters(TCase *tc); void evas_test_image_object(TCase *tc); void evas_test_mesh(TCase *tc); void evas_test_mask(TCase *tc); +void evas_test_evasgl(TCase *tc); #endif /* _EVAS_SUITE_H */ diff --git a/src/tests/evas/evas_test_evasgl.c b/src/tests/evas/evas_test_evasgl.c new file mode 100644 index 0000000000..af840b5da1 --- /dev/null +++ b/src/tests/evas/evas_test_evasgl.c @@ -0,0 +1,250 @@ +/* Test Evas GL EAPIs. + * + * This will try with opengl_x11 and buffer (OSMesa) and silently fail if + * the engine or the GL library can't be initialized. This is to test Evas GL + * APIs when they can actually work, ie. when OSMesa exists or when the engine + * is GL. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#define EFL_GFX_FILTER_BETA +#include "evas_suite.h" +#include "Evas.h" +#include "Evas_GL.h" +#include "Ecore_Evas.h" + +static int +_detect_osmesa(void) +{ + /* assume that if libOSMesa.so links, then we can create an Evas GL */ + void *lib = dlopen("libOSMesa.so", RTLD_NOW); + if (!lib) + { + printf("Could not find OSMesa! Skipping Evas GL tests.\n"); + return 0; + } + dlclose(lib); + return 1; +} + +#define START_EVASGL_TEST(engine, options) \ + Ecore_Evas *ee; Evas *evas; Evas_Object *im = NULL; \ + if (!strcmp(engine, "buffer") && !_detect_osmesa()) return; \ + putenv("EVAS_GL_API_DEBUG=1"); \ + evas_init(); \ + ecore_evas_init(); \ + ee = ecore_evas_new(engine, 0, 0, 1, 1, options); \ + if (!ee) { printf("Could not create ecore evas. Skipping Evas GL tests.\n"); \ + goto init_failed; } \ + ecore_evas_show(ee); \ + ecore_evas_manual_render_set(ee, EINA_TRUE); \ + evas = ecore_evas_get(ee); \ + im = evas_object_image_filled_add(evas); \ + evas_object_geometry_set(im, 0, 0, 1, 1); \ + evas_object_show(im); \ + ecore_evas_manual_render(ee); \ + do {} while (0) + +#define END_EVASGL_TEST() \ + init_failed: \ + evas_object_del(im); \ + ecore_evas_free(ee); \ + ecore_evas_shutdown(); \ + evas_shutdown(); \ + do {} while (0) + +static void +_test_evasgl_init(const char *engine, const char *options) +{ + START_EVASGL_TEST(engine, options); + Evas_GL_Context *ctx; + Evas_GL_Surface *sfc; + Evas_GL_Config *cfg; + Evas_GL_API *gl; + Evas_GL *evgl; + + fail_if(!(evgl = evas_gl_new(evas))); + fail_if(!(cfg = evas_gl_config_new())); + fail_if(!(sfc = evas_gl_surface_create(evgl, cfg, 1, 1))); + fail_if(!(ctx = evas_gl_context_create(evgl, NULL))); + + /* valid current states */ + fail_if(!evas_gl_make_current(evgl, sfc, ctx)); + fail_if(!evas_gl_make_current(evgl, NULL, NULL)); + fail_if(!evas_gl_make_current(evgl, NULL, ctx)); + + /* no context but surface: invalid */ + fprintf(stderr, "================ IGNORE ERRORS BEGIN ================\n"); + fail_if(evas_gl_make_current(evgl, sfc, NULL) != EINA_FALSE); + fprintf(stderr, "================ IGNORE ERRORS END ================\n"); + + /* API verification */ + fail_if(!(gl = evas_gl_api_get(evgl))); + + fail_if(!evas_gl_make_current(evgl, NULL, NULL)); + evas_gl_context_destroy(evgl, ctx); + evas_gl_surface_destroy(evgl, sfc); + evas_gl_config_free(cfg); + evas_gl_free(evgl); + + END_EVASGL_TEST(); +} + +static void +_test_evasgl_current_get(const char *engine, const char *options) +{ + if (!_detect_osmesa()) + return; + + START_EVASGL_TEST(engine, options); + Evas_GL_Context *ctx, *ctx2; + Evas_GL_Surface *sfc, *sfc2; + Evas_GL_Config *cfg; + Evas_GL *evgl, *evgl2; + + ctx2 = (void*)(intptr_t)0x1; + sfc2 = (void*)(intptr_t)0x1; + evgl2 = evas_gl_current_evas_gl_get(&ctx2, &sfc2); + fail_if(evgl2 || ctx2 || sfc2); + + fail_if(!(evgl = evas_gl_new(evas))); + fail_if(!(cfg = evas_gl_config_new())); + fail_if(!(sfc = evas_gl_surface_create(evgl, cfg, 1, 1))); + fail_if(!(ctx = evas_gl_context_create(evgl, NULL))); + + ctx2 = (void*)(intptr_t)0x1; + sfc2 = (void*)(intptr_t)0x1; + evgl2 = evas_gl_current_evas_gl_get(&ctx2, &sfc2); + fail_if(evgl2 || ctx2 || sfc2); + + fail_if(!evas_gl_make_current(evgl, sfc, ctx)); + evgl2 = evas_gl_current_evas_gl_get(&ctx2, &sfc2); + fail_if(evgl2 != evgl); + fail_if(sfc2 != sfc); + fail_if(ctx2 != ctx); + + fail_if(!evas_gl_make_current(evgl, NULL, NULL)); + evgl2 = evas_gl_current_evas_gl_get(&ctx2, &sfc2); + fail_if(evgl2 != evgl); /* this should not reset current Evas GL */ + fail_if(sfc2 != NULL); + fail_if(ctx2 != NULL); + + evas_gl_context_destroy(evgl, ctx); + evas_gl_surface_destroy(evgl, sfc); + evas_gl_free(evgl); + END_EVASGL_TEST(); +} + +static void +_test_evasgl_context_version(const char *engine, const char *options) +{ + if (!_detect_osmesa()) + return; + + START_EVASGL_TEST(engine, options); + Evas_GL_Context *ctx, *ctx2; + Evas_GL_Surface *sfc; + Evas_GL_Config *cfg; + Evas_GL_API *gl; + Evas_GL *evgl; + const char *ver, *ext, *glsl; + int vmaj, vmin; + + fail_if(!(evgl = evas_gl_new(evas))); + fail_if(!(cfg = evas_gl_config_new())); + fail_if(!(sfc = evas_gl_surface_create(evgl, cfg, 1, 1))); + + /* test only GLES 2 - GLES 3 and GLES 1 not supported yet with OSMesa */ + fail_if(!(ctx = evas_gl_context_version_create(evgl, NULL, EVAS_GL_GLES_2_X))); + fail_if(!(gl = evas_gl_api_get(evgl))); + fail_if(gl->version != EVAS_GL_API_VERSION); /* valid for make check */ + + fail_if(!evas_gl_make_current(evgl, sfc, ctx)); + fail_if(!(ver = (const char *) gl->glGetString(GL_VERSION))); + printf("GL_VERSION: %s\n", ver); + fail_if(sscanf(ver, "OpenGL ES %d.%d", &vmaj, &vmin) != 2); + fail_if((vmaj < 2) || (vmin < 0)); + + /* verify function pointers - GLES 2 only */ + typedef void (*fptr_t)(); + const int idx_glViewport = ((char*) &gl->glViewport - (char*) &gl->glActiveTexture) / sizeof(fptr_t); + fptr_t *fptr= &gl->glActiveTexture; + for (int i = 0; i < idx_glViewport; i++, fptr++) + fail_if(!*fptr); + + /* mesa supports a ton of extensions but there are no extra pointers set in + * Evas_GL_API for those extensions */ + fail_if(!(ext = (const char *) gl->glGetString(GL_EXTENSIONS))); + printf("GL_EXTENSIONS: %s\n", ext); + + /* GLSL string format check */ + fail_if(!(glsl = (const char *) gl->glGetString(GL_SHADING_LANGUAGE_VERSION))); + printf("GL_SHADING_LANGUAGE_VERSION: %s\n", glsl); + fail_if(sscanf(glsl, "OpenGL ES GLSL ES %d", &vmaj) != 1); + + /* shared ctx */ + fail_if(!(ctx2 = evas_gl_context_version_create(evgl, ctx, EVAS_GL_GLES_2_X))); + evas_gl_context_destroy(evgl, ctx2); + + fail_if(!evas_gl_make_current(evgl, NULL, NULL)); + evas_gl_context_destroy(evgl, ctx); + evas_gl_surface_destroy(evgl, sfc); + evas_gl_free(evgl); + END_EVASGL_TEST(); +} + +START_TEST(evas_test_evasgl_init_opengl_x11) +{ + _test_evasgl_init("opengl_x11", NULL); +} +END_TEST + +START_TEST(evas_test_evasgl_current_get_opengl_x11) +{ + _test_evasgl_current_get("opengl_x11", NULL); +} +END_TEST + +START_TEST(evas_test_evasgl_context_version_opengl_x11) +{ + _test_evasgl_context_version("opengl_x11", NULL); +} +END_TEST + +START_TEST(evas_test_evasgl_init_buffer) +{ + _test_evasgl_init("buffer", NULL); +} +END_TEST + +START_TEST(evas_test_evasgl_current_get_buffer) +{ + _test_evasgl_current_get("buffer", NULL); +} +END_TEST + +START_TEST(evas_test_evasgl_context_version_buffer) +{ + _test_evasgl_context_version("buffer", NULL); +} +END_TEST + +void evas_test_evasgl(TCase *tc) +{ + if (getenv("DISPLAY")) + { + tcase_add_test(tc, evas_test_evasgl_init_opengl_x11); + tcase_add_test(tc, evas_test_evasgl_current_get_opengl_x11); + tcase_add_test(tc, evas_test_evasgl_context_version_opengl_x11); + } + + tcase_add_test(tc, evas_test_evasgl_init_buffer); + tcase_add_test(tc, evas_test_evasgl_current_get_buffer); + tcase_add_test(tc, evas_test_evasgl_context_version_buffer); +}