From 7b401f34dac59e118286c02fa2260c92eead2310 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Thu, 15 Oct 2015 16:02:02 +0900 Subject: [PATCH] Evas GL: Add more tests - glReadPixels - FBO test - PBuffer test (only GL engine) - surface formats test (up to depth=24, stencil=8) --- src/tests/evas/evas_test_evasgl.c | 304 +++++++++++++++++++++++++++++++++++--- 1 file changed, 281 insertions(+), 23 deletions(-) diff --git a/src/tests/evas/evas_test_evasgl.c b/src/tests/evas/evas_test_evasgl.c index 6ee7c92..cba2192 100644 --- a/src/tests/evas/evas_test_evasgl.c +++ b/src/tests/evas/evas_test_evasgl.c @@ -39,7 +39,8 @@ _detect_osmesa(void) putenv("EVAS_GL_API_DEBUG=1"); \ evas_init(); \ ecore_evas_init(); \ - ee = ecore_evas_new(engine, 0, 0, 1, 1, options); \ + if (!options || !strcmp(engine, "buffer")) ee = ecore_evas_new(engine, 0, 0, 1, 1, NULL); \ + else ee = ecore_evas_gl_x11_options_new(NULL, NULL, 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); \ @@ -60,9 +61,9 @@ _detect_osmesa(void) do {} while (0) static void -_test_evasgl_init(const char *engine, const char *options) +_test_evasgl_init(const char *engine) { - START_EVASGL_TEST(engine, options); + START_EVASGL_TEST(engine, NULL); Evas_GL_Context *ctx; Evas_GL_Surface *sfc; Evas_GL_Config *cfg; @@ -96,12 +97,9 @@ _test_evasgl_init(const char *engine, const char *options) } static void -_test_evasgl_current_get(const char *engine, const char *options) +_test_evasgl_current_get(const char *engine) { - if (!_detect_osmesa()) - return; - - START_EVASGL_TEST(engine, options); + START_EVASGL_TEST(engine, NULL); Evas_GL_Context *ctx, *ctx2; Evas_GL_Surface *sfc, *sfc2; Evas_GL_Config *cfg; @@ -127,12 +125,16 @@ _test_evasgl_current_get(const char *engine, const char *options) fail_if(evgl2 != evgl); fail_if(sfc2 != sfc); fail_if(ctx2 != ctx); + fail_if(evas_gl_current_surface_get(evgl) != sfc); + fail_if(evas_gl_current_context_get(evgl) != 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); + fail_if(evas_gl_current_surface_get(evgl)); + fail_if(evas_gl_current_context_get(evgl)); evas_gl_context_destroy(evgl, ctx); evas_gl_surface_destroy(evgl, sfc); @@ -141,12 +143,9 @@ _test_evasgl_current_get(const char *engine, const char *options) } static void -_test_evasgl_context_version(const char *engine, const char *options) +_test_evasgl_context_version(const char *engine) { - if (!_detect_osmesa()) - return; - - START_EVASGL_TEST(engine, options); + START_EVASGL_TEST(engine, NULL); Evas_GL_Context *ctx, *ctx2; Evas_GL_Surface *sfc; Evas_GL_Config *cfg; @@ -199,12 +198,9 @@ _test_evasgl_context_version(const char *engine, const char *options) } static void -_test_evasgl_surfaceless_context(const char *engine, const char *options) +_test_evasgl_surfaceless_context(const char *engine) { - if (!_detect_osmesa()) - return; - - START_EVASGL_TEST(engine, options); + START_EVASGL_TEST(engine, NULL); Evas_GL_Context *ctx; Evas_GL_Surface *sfc; Evas_GL_Config *cfg; @@ -215,40 +211,294 @@ _test_evasgl_surfaceless_context(const char *engine, const char *options) fail_if(!(evgl = evas_gl_new(evas))); fail_if(!(ctx = evas_gl_context_create(evgl, NULL))); - // FIXME: evas_gl_string_query will fail before the first make_current + // FIXME: evas_gl_string_query will fail before the first make_current (GL) fail_if(!(cfg = evas_gl_config_new())); fail_if(!(sfc = evas_gl_surface_create(evgl, cfg, 1, 1))); fail_if(!evas_gl_make_current(evgl, sfc, ctx)); // FIXME + fail_if(!(gl = evas_gl_context_api_get(evgl, ctx))); + eexts = evas_gl_string_query(evgl, EVAS_GL_EXTENSIONS); if (eexts && strstr(eexts, "EGL_KHR_surfaceless_context")) { fail_if(!evas_gl_make_current(evgl, NULL, ctx)); - fail_if(!(gl = evas_gl_context_api_get(evgl, ctx))); fail_if(!gl->glGetString(GL_VERSION)); } else printf("Surfaceless context not supported. Skipped.\n"); 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_glreadpixels(const char *engine) +{ + /* simple test verifying surface render works as expected */ + + START_EVASGL_TEST(engine, NULL); + Evas_GL_Context *ctx; + Evas_GL_Surface *sfc; + Evas_GL_Config *cfg; + Evas_GL_API *gl; + Evas_GL *evgl; + unsigned int pixel; + + fail_if(!(evgl = evas_gl_new(evas))); + fail_if(!(cfg = evas_gl_config_new())); + fail_if(!(ctx = evas_gl_context_create(evgl, NULL))); + fail_if(!(sfc = evas_gl_surface_create(evgl, cfg, 1, 1))); + fail_if(!evas_gl_make_current(evgl, sfc, ctx)); + fail_if(!(gl = evas_gl_context_api_get(evgl, ctx))); + + gl->glClearColor(0, 1, 0, 1); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel); + fail_if(gl->glGetError() != GL_NO_ERROR); + fail_if(pixel != 0xFF00FF00); + + 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_fbo(const char *engine) +{ + /* simple test verifying FBO render works as expected */ + + START_EVASGL_TEST(engine, NULL); + Evas_GL_Context *ctx; + Evas_GL_Surface *sfc; + Evas_GL_Config *cfg; + Evas_GL_API *gl; + Evas_GL *evgl; + unsigned int pixel; + GLuint fbo, tex, vtx, frg, prg, u; + GLint status; + + static const char *vertex = + "precision mediump float;\n" + "attribute vec4 vertex;\n" + "void main()\n" + "{\n" + " gl_Position = vertex;\n" + "}\n"; + static const char *fragment = + "precision mediump float;\n" + "uniform vec4 color;\n" + "void main()\n" + "{\n" + " gl_FragColor = color;\n" + "}\n"; + static const GLfloat color[] = { 1, 0, 0, 1 }; + static const GLfloat vertices[] = { + 1.0, 1.0, 0.0, + -1.0, -1.0, 0.0, + 1.0, -1.0, 0.0, + 1.0, 1.0, 0.0, + -1.0, 1.0, 0.0, + -1.0, -1.0, 0.0 + }; + + /* surface & context */ + fail_if(!(evgl = evas_gl_new(evas))); + fail_if(!(cfg = evas_gl_config_new())); + cfg->color_format = EVAS_GL_RGBA_8888; + fail_if(!(ctx = evas_gl_context_create(evgl, NULL))); + fail_if(!(sfc = evas_gl_surface_create(evgl, cfg, 1, 1))); + fail_if(!evas_gl_make_current(evgl, sfc, ctx)); + fail_if(!(gl = evas_gl_context_api_get(evgl, ctx))); + + /* generate fbo */ + gl->glGenFramebuffers(1, &fbo); + gl->glGenTextures(1, &tex); + gl->glBindFramebuffer(GL_FRAMEBUFFER, fbo); + gl->glBindTexture(GL_TEXTURE_2D, tex); + gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); + fail_if(gl->glGetError() != GL_NO_ERROR); + + /* prepare program */ + vtx = gl->glCreateShader(GL_VERTEX_SHADER); + gl->glShaderSource(vtx, 1, &vertex, NULL); + gl->glCompileShader(vtx); + gl->glGetShaderiv(vtx, GL_COMPILE_STATUS, &status); + fail_if((gl->glGetError() != GL_NO_ERROR) || !status); + frg = gl->glCreateShader(GL_FRAGMENT_SHADER); + gl->glShaderSource(frg, 1, &fragment, NULL); + gl->glCompileShader(frg); + gl->glGetShaderiv(frg, GL_COMPILE_STATUS, &status); + fail_if((gl->glGetError() != GL_NO_ERROR) || !status); + prg = gl->glCreateProgram(); + gl->glAttachShader(prg, vtx); + gl->glAttachShader(prg, frg); + gl->glBindAttribLocation(prg, 0, "vertex"); + gl->glLinkProgram(prg); + gl->glGetProgramiv(prg, GL_LINK_STATUS, &status); + fail_if((gl->glGetError() != GL_NO_ERROR) || !status); + + /* clear */ + gl->glClearColor(0, 0, 0, 0); + gl->glClear(GL_COLOR_BUFFER_BIT); + fail_if(gl->glGetError() != GL_NO_ERROR); + + /* set parameters */ + gl->glUseProgram(prg); + u = gl->glGetUniformLocation(prg, "color"); + gl->glUniform4fv(u, 1, color); + gl->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices); + gl->glEnableVertexAttribArray(0); + fail_if(gl->glGetError() != GL_NO_ERROR); + + /* draw */ + gl->glDrawArrays(GL_TRIANGLES, 0, 6); + gl->glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel); + fail_if(gl->glGetError() != GL_NO_ERROR); + fail_if(pixel != 0xFF0000FF); + + 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_pbuffer(const char *engine) +{ + /* check support for PBuffer */ + + // FIXME: No SW engine support! + if (!strcmp(engine, "buffer")) + { + printf("PBuffer not supported (SW engine). Skipped.\n"); + return; + } + + START_EVASGL_TEST(engine, NULL); + Evas_GL_Context *ctx; + Evas_GL_Surface *sfc; + Evas_GL_Config *cfg; + Evas_GL_API *gl; + Evas_GL *evgl; + unsigned int pixel; + + fail_if(!(evgl = evas_gl_new(evas))); + fail_if(!(cfg = evas_gl_config_new())); + cfg->color_format = EVAS_GL_RGBA_8888; + fail_if(!(ctx = evas_gl_context_create(evgl, NULL))); + fail_if(!(sfc = evas_gl_pbuffer_surface_create(evgl, cfg, 1, 1, NULL))); + fail_if(!evas_gl_make_current(evgl, sfc, ctx)); + fail_if(!(gl = evas_gl_context_api_get(evgl, ctx))); + + /* clear */ + gl->glClearColor(0, 1, 0, 1); + gl->glClear(GL_COLOR_BUFFER_BIT); + gl->glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel); + fail_if(gl->glGetError() != GL_NO_ERROR); + fail_if(pixel != 0xFF00FF00); + + 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_formats(const char *engine) +{ + /* check that Evas GL always falls back to working surface configs */ + + const int options[] = { ECORE_EVAS_GL_X11_OPT_GL_DEPTH, 24, + ECORE_EVAS_GL_X11_OPT_GL_STENCIL, 8, + ECORE_EVAS_GL_X11_OPT_GL_MSAA, 4, + 0 }; + const int *opts = options; + START_EVASGL_TEST(engine, opts); + Evas_GL_Context *ctx; + Evas_GL_Surface *sfc; + Evas_GL_Config *cfg; + Evas_GL *evgl; + + fail_if(!(evgl = evas_gl_new(evas))); + fail_if(!(cfg = evas_gl_config_new())); + fail_if(!(ctx = evas_gl_context_create(evgl, NULL))); + + // don't test DEPTH_32 or STENCIL_16 + for (Evas_GL_Color_Format fmt = EVAS_GL_RGB_888; fmt < EVAS_GL_NO_FBO; fmt++) + for (Evas_GL_Depth_Bits depth = EVAS_GL_DEPTH_NONE; depth <= EVAS_GL_DEPTH_BIT_24; depth++) + for (Evas_GL_Stencil_Bits stencil = EVAS_GL_STENCIL_NONE; stencil <= EVAS_GL_STENCIL_BIT_8; stencil++) + for (Evas_GL_Options_Bits opt = EVAS_GL_OPTIONS_NONE; opt <= 2; opt += 2) + for (Evas_GL_Multisample_Bits msaa = EVAS_GL_MULTISAMPLE_NONE; msaa <= EVAS_GL_MULTISAMPLE_HIGH; msaa++) + { + cfg->color_format = fmt; + cfg->depth_bits = depth; + cfg->stencil_bits = stencil; + cfg->options_bits = opt; + cfg->multisample_bits = msaa; + cfg->gles_version = EVAS_GL_GLES_2_X; + /* + fprintf(stderr, "Testing surface %d %d %d %d %d\n", + cfg->color_format, cfg->depth_bits, cfg->stencil_bits, + cfg->multisample_bits, cfg->options_bits); + */ + fail_if(!(sfc = evas_gl_surface_create(evgl, cfg, 1, 1))); + fail_if(!evas_gl_make_current(evgl, sfc, ctx)); + fail_if(!evas_gl_make_current(evgl, NULL, NULL)); + evas_gl_surface_destroy(evgl, sfc); + } + + fail_if(!evas_gl_make_current(evgl, NULL, NULL)); + evas_gl_context_destroy(evgl, ctx); + evas_gl_config_free(cfg); + evas_gl_free(evgl); END_EVASGL_TEST(); } -#define TEST_ADD(name) \ +#define TEST_ADD_OPT(name, opt) \ START_TEST(evas ## name ## _opengl_x11) \ - { name("opengl_x11", NULL); } \ + { name("opengl_x11"); } \ END_TEST \ START_TEST(evas ## name ## _buffer) \ - { name("buffer", NULL); } \ + { name("buffer"); } \ END_TEST +#define TEST_ADD(name) TEST_ADD_OPT(name, NULL) TEST_ADD(_test_evasgl_init) TEST_ADD(_test_evasgl_current_get) TEST_ADD(_test_evasgl_context_version) TEST_ADD(_test_evasgl_surfaceless_context) +TEST_ADD(_test_evasgl_glreadpixels) +TEST_ADD(_test_evasgl_fbo) +TEST_ADD(_test_evasgl_formats) +TEST_ADD(_test_evasgl_pbuffer) + +/* APIs still to test: + * + * evas_gl_rotation_get + * evas_gl_surface_query + * evas_gl_error_get + * evas_gl_native_surface_get + * evas_gl_proc_address_get + * + * Most of these actually need support in SW engine to be improved. + */ void evas_test_evasgl(TCase *tc) { @@ -261,6 +511,10 @@ void evas_test_evasgl(TCase *tc) TEST_ADD(_test_evasgl_current_get); TEST_ADD(_test_evasgl_context_version); TEST_ADD(_test_evasgl_surfaceless_context); + TEST_ADD(_test_evasgl_glreadpixels); + TEST_ADD(_test_evasgl_fbo); + TEST_ADD(_test_evasgl_pbuffer); + TEST_ADD(_test_evasgl_formats); } #undef TEST_ADD @@ -270,4 +524,8 @@ void evas_test_evasgl(TCase *tc) TEST_ADD(_test_evasgl_current_get); TEST_ADD(_test_evasgl_context_version); TEST_ADD(_test_evasgl_surfaceless_context); + TEST_ADD(_test_evasgl_glreadpixels); + TEST_ADD(_test_evasgl_fbo); + TEST_ADD(_test_evasgl_pbuffer); + TEST_ADD(_test_evasgl_formats); } -- 2.7.4