Evas GL: Add more tests
authorJean-Philippe Andre <jp.andre@samsung.com>
Thu, 15 Oct 2015 07:02:02 +0000 (16:02 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Thu, 15 Oct 2015 07:20:53 +0000 (16:20 +0900)
- glReadPixels
- FBO test
- PBuffer test (only GL engine)
- surface formats test (up to depth=24, stencil=8)

src/tests/evas/evas_test_evasgl.c

index 6ee7c92..cba2192 100644 (file)
@@ -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);
 }