Hi all,

In my earlier post, I've discussed about the issues with getting the

      evas_object_image_native_surface_set(..., Evas_Native_Surface *surf);

function for setting OpenGL output texture.

The main issue was the GL application having to know Evas' GL context for
resource
sharing.  (refer to the older post if this doesn't make sense).  Exposing
Evas'
GL context is just a bad idea and it makes things really ugly.

One idea that Cedric mentioned as a response was to have evas provide APIs
that create OpenGL context for the user so everything can be hidden.

I actually had the same idea and the previous post was a way for me to setup
a
discussion ground for what I'm about to propose.

Instead of just exposing apis for creating contexts, I thought it would be
nice
for Evas to provide the OpenGL glue layer for the user.  When I say glue
layer,
I'm talking about GLX (for X evn in linux), WGL (for windows) and CGL (for
mac).
The Evas glue layer would provide functions such
as surface/context creation, make current function and etc.  this allows
evas to
hide all the backend specific code in the evas engine and have user deal
with
the provided APIs.  This goes along with EFL philosophy I believe.

For surface implementation, the engine can simply create an FBO and a
render target texture for the user to render to.  The texture can be used to
for setting the native_surface function.

There are two way to go about providing the APIs.  One approach is to have
evas fill out a list of functions from the engine.  This can be similar to
Evas_Engine_Info_GL_X11.

for example,
//--------------------------------//
// Option 1
struct _Evas_GL_Info
{
   int                  version;

   struct {
      Display                  *display;
      Evas_GL_API        api;
   } info;

   struct {
      Evas_GL_Contex    *(*create_context)(Evas_GL_Info *info);
      Evas_GL_Surface   *(*create_surface)(Evas_GL_Info *info, const
Evas_GL_Config *config);
      Eina_Bool                (*make_current)(Evas_GL_Info *info,
Evas_GL_Context *context, Evas_GL_Surface *surface);
      Evas_GL_Func        (*get_proc_address)(const char *proc_name);
      const char              *(*query_extension)(void);
      // Need functions that destroy contexts and etc...
   } func;
};

EAPI Evas_GL_Info    *evas_gl_info_get(Evas *e);

// Usage Example
int main()
{
   Evas e* = ...;

   Evas_GL_Info    *glinfo;
   Evas_GL_Context *ctx;
   Evas_GL_Surface *sfc;
   Evas_GL_Config  cfg = {...};
   Evas_Native_Surface ns;

   glinfo = evas_gl_info_get(e);
   ctx = glinfo->func->create_context(glinfo, EVAS_GL_API_GLES_2);
   sfc = glinfo->func->create_surface(glinfo, cfg);

   glinfo->func->make_current(glinfo, ctx, sfc);

   // Use tex and the info in the surface to attach it to the image_object
   ns.data.opengl.texture_id = sfc->data.gl.tex;
   ...

   return 0;
}

//--------------------------------//
Another option is to provide evas-like APIs.

// Option 2
EAPI Evas_GL                      *evas_gl_new                     (Evas
*e);
EAPI Evas_GL_Surface         *evas_gl_surface_create     (Evas_GL *evas_gl,
Evas_GL_Config *cfg, int w, int h);
EAPI Evas_EFGL_Context     *evas_gl_context_create     (Evas_GL *evas_gl);
EAPI Eina_Bool                      evas_gl_make_current       (Evas_GL
*evas_gl, Evas_GL_Surface *sfc, Evas_EFGL_Context *ctx);
EAPI Evas_GL_Func              evas_gl_proc_address_get (Evas_GL *evas_gl,
const char *name);

EAPI Eina_Bool                     evas_gl_native_surface_get (Evas_GL
*evas_gl, Evas_GL_Surface *sfc, Evas_Native_Surface *ns);

// Usage Example
int main (void)
{
    Evas e* = ...;

    EvasGL *evasgl;
    EvasGL_Surface *sfc;
    EvasGL_Context *ctx;
    EvasGL_Config cfg = { ... };
    Evas_Native_Surface ns;

    evasgl = evasgl_get(canvas);
    sfc = evasgl_create_surface(evasgl, &cfg, w, h);
    ctx = evasgl_create_context(evasgl);

    evasgl_make_current(evasgl, sfc, ctx);

    // GL Calls...
    ...

    // Get the native surface from EvasGL surface to attach it to the image
object
    evasgl_native_surface_get (evasgl, *sfc, &ns);
    ...
}

//--------------------------//
Personally, I like the option 2 because the APIs look more Evas-like and
it's evas engine neutral.

Now, there are a few issues with implementing a glue layer in Evas.

- One major issue is that internally, the surface that the evas provides is
implemented using an FBO. Semantically, FBO index 0 is the main framebuffer
of the screen.  So, when user calls, glBindFramebuffer(GL_FRAMEBUFFER, 0);
the user expects the framebuffer of the surface.  Unfortunately, this isn't
true
when using the evas provided surface. So we'll need to either advise
developers
not to call glBindFramebuffer(GL_FRAMEBUFFER, 0) or hook that
function and have it do what we want to do.  Another idea that came up is
have evas provide a list of GL functions that it supports. That can be
debated later.

- Another issue is that because the application would run in the same thread
as evas,
the GL application would need to do a make_current every time he wants
something
drawn.  This is because there is a context switch when Evas draws something
to
its output canvas.  We can consider rendering it in a different thread but
my understanding is that Evas is not MT safe.

I'm attaching a sample Evas_GL.h header and a sample program that would use
the apis.  In the header, I've just filled out the config enums without
putting too much
thought into it so don't flame me for that just yet =)  Also, I actually
have the above
headers implemented but I'll wait until the community decides on a set of
APIs and then submit a patch for review.

comments would be much appreciated. thanks!

cheers,
Sung
#ifndef _EVAS_GL_H
#define _EVAS_GL_H

#include <Evas.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct _Evas_GL               Evas_GL;
typedef struct _Evas_GL_Surface       Evas_GL_Surface;
typedef struct _Evas_GL_Context     Evas_GL_Context;
typedef struct _Evas_GL_Config        Evas_GL_Config;
typedef void*                         Evas_GL_Func;

typedef enum _Evas_GL_Color_Format
{
    EVAS_GL_RGB_8,      // 8 bits per channel
    EVAS_GL_RGBA_8,
    EVAS_GL_RGB_32,     // 32-bits per channel
    EVAS_GL_RGBA_32,
} Evas_GL_Color_Format;

typedef enum _Evas_GL_Depth_Bits
{
    EVAS_GL_DEPTH_BIT_8,
    EVAS_GL_DEPTH_BIT_16,
    EVAS_GL_DEPTH_BIT_24,
    EVAS_GL_DEPTH_BIT_32,
    EVAS_GL_DEPTH_NONE
} Evas_GL_Depth_Bits;

typedef enum _Evas_GL_Stencil_Bits
{
    EVAS_GL_STENCIL_BIT_1,
    EVAS_GL_STENCIL_BIT_2,
    EVAS_GL_STENCIL_BIT_4,
    EVAS_GL_STENCIL_BIT_8,
    EVAS_GL_STENCIL_BIT_16,
    EVAS_GL_STENCIL_NONE
} Evas_GL_Stencil_Bits;

struct _Evas_GL_Config
{
    Evas_GL_Color_Format     color_format;
    Evas_GL_Depth_Bits       depth_bits;
    Evas_GL_Stencil_Bits     stencil_bits;
};

/**
 * @defgroup Evas_GL group for rendering GL on Evas
 *
 * Functions that are used to do GL rendering on Evas.
 *
 * @ingroup Evas_Canvas
 */

   EAPI Evas_GL                 *evas_gl_new                (Evas *e);
   EAPI void                     evas_gl_free               (Evas_GL *evas_gl);
   EAPI Evas_GL_Surface         *evas_gl_surface_create     (Evas_GL *evas_gl, Evas_GL_Config *cfg, int w, int h);
   EAPI void                     evas_gl_surface_destroy    (Evas_GL *evas_gl, Evas_GL_Surface *sfc); 
   EAPI Evas_GL_Context         *evas_gl_context_create     (Evas_GL *evas_gl); 
   EAPI void                     evas_gl_context_destroy    (Evas_GL *evas_gl, Evas_GL_Context *ctx); 
   EAPI Eina_Bool                evas_gl_make_current       (Evas_GL *evas_gl, Evas_GL_Surface *sfc, Evas_GL_Context *ctx);
   EAPI Evas_GL_Func             evas_gl_proc_address_get   (Evas_GL *evas_gl, const char *name);

   EAPI Eina_Bool                evas_gl_native_surface_get (Evas_GL *evas_gl, Evas_GL_Surface *sfc, Evas_Native_Surface *ns);
 
//   EAPI Evas_GL                 *evas_gl_api_get            (Evas *e, Evas_GL_API *glapi) EINA_ARG_NONNULL(1, 2);



#ifdef __cplusplus
}
#endif

#endif
/**
 * Simple Evas_GL example
 */
#include <Ecore_Evas.h>
#include <Ecore.h>
#include <Evas_GL.h>
#include <stdio.h>
#include <GL/gl.h>

#define WIDTH (512)
#define HEIGHT (512)

static void init_gl(Evas *evas);
static void draw_gl();
static void free_gl();

static Ecore_Evas  *ee;
static Evas_GL *evasgl;
static Evas_GL_Surface *sfc;
static Evas_GL_Context *ctx;

int main(void)
{
   Evas *canvas;
   Evas_Object *r1;
   Evas_Native_Surface ns;

   ecore_init();
   ecore_evas_init();

   ee = ecore_evas_gl_x11_new(NULL, 0, 0, 0, WIDTH, HEIGHT);
   ecore_evas_title_set(ee, "Ecore_Evas Template");
   ecore_evas_borderless_set(ee, 0);
   ecore_evas_show(ee);

   canvas = ecore_evas_get(ee);

   // Initialize GL Stuff
   init_gl(canvas);

   // Draw a Triangle
   draw_gl();

   // Get the Native_Surface from EvasGL
   evas_gl_native_surface_get(evasgl, sfc, &ns);

   // EvasImage Object
   r1 = evas_object_image_add(canvas);
   evas_object_image_fill_set(r1, 0, 0, 256, 256);
   evas_object_move(r1, 128, 128);
   evas_object_image_load_size_set(r1, 256, 256);
   evas_object_resize(r1, 256, 256);
   evas_object_image_size_set(r1, 256, 256);
   //evas_object_image_data_set(r1, (void*)data);
   evas_object_image_native_surface_set(r1, &ns);
   evas_object_show(r1);

   ecore_main_loop_begin();

   free_gl();

   ecore_evas_shutdown();
   ecore_shutdown();

   return 0;
}

static void init_gl(Evas *evas)
{
   Evas_GL_Config config = {EVAS_GL_RGBA_8, 
        EVAS_GL_DEPTH_NONE, 
        EVAS_GL_STENCIL_NONE };
   int w, h;

   w = 256; 
   h = 256;

   evasgl = evas_gl_new(evas);
   sfc = evas_gl_surface_create(evasgl, &config, w, h);
   ctx = evas_gl_context_create(evasgl);

   evas_gl_make_current(evasgl, sfc, ctx);

   // GL Init Stuff
   glViewport(0, 0, w, h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glOrtho(0, w, 0, h, -1, 1);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();

   glClearColor(0.3,0.3,0.3,1);
   glClear(GL_COLOR_BUFFER_BIT);

}

static void draw_gl()
{
   // In a dynamic scene, make_current has to be called every time.
   //evas_gl_make_current(evasgl, NULL, NULL);

   // Draw a Triangle
   glEnable(GL_BLEND);
   glBegin(GL_TRIANGLES);
   glColor3f(1, 0, 0);
   glVertex3f(20, 20, 0);
   glColor3f(0, 1, 0);
   glVertex3f(236, 20, 0);
   glColor3f(0, 0, 1);
   glVertex3f(128, 236, 0);
   glEnd();

}

static void free_gl()
{
   evas_gl_surface_destroy(evasgl, sfc);
   evas_gl_context_destroy(evasgl, ctx);

   evas_gl_free(evasgl);
}

/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
------------------------------------------------------------------------------
Free Software Download: Index, Search & Analyze Logs and other IT data in 
Real-Time with Splunk. Collect, index and harness all the fast moving IT data 
generated by your applications, servers and devices whether physical, virtual
or in the cloud. Deliver compliance at lower cost and gain new business 
insights. http://p.sf.net/sfu/splunk-dev2dev 
_______________________________________________
enlightenment-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to