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. There was also a disucssion
about how Evas should provide a GL glue layer. We've discussed two
proposals.
After some discussion, I went ahead with the preferred way and have
implemented the APIs.
The APIs go something like... (in Evas_GL.h)
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_GL_Context *evas_gl_context_create (Evas_GL *evas_gl,
Evas_GL_Context *share_ctx);
EAPI Eina_Bool evas_gl_make_current (Evas_GL
*evas_gl, Evas_GL_Surface *surf, 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 *surf, Evas_Native_Surface *ns);
I actually have the above APIs running on my machine but
instead of dumping the entire thing, I wanted to get incremental comments
for review.
I'm now attaching Evas_GL.h and evas_gl.c and a Sample program that uses the
APIs.
Your comments would be very much appreciated. After the initial review,
I'll submit
a RFC for the engine part of the code that I wrote for gl_x11 module.
One issue that I ran into with the above APIs is that Evas_GL_Context is
already used
by the gl_common part of the code in the engine module. Upon discussing it
with Raster,
the consensus was that it was better to change the internal code since it's
not exposed.
So, in my implementation, I've changed the internal part to
Evas_Engine_GL_Context.
I just wanted to mention that here for now even though it won't show in the
files that i'm
attaching.
thanks!
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 *surf);
EAPI Evas_GL_Context *evas_gl_context_create (Evas_GL *evas_gl, Evas_GL_Context *share_ctx);
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 *surf, 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 *surf, 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
#include "evas_common.h"
#include "evas_private.h"
#include "Evas_GL.h"
struct _Evas_GL
{
int magic;
Evas *evas;
};
struct _Evas_GL_Context
{
void *data;
};
struct _Evas_GL_Surface
{
void *data;
};
/**
* @addtogroup Evas_GL
* @{
*/
/**
* Creates a new Evas_GL object and returns a handle for gl rendering on efl.
*
* @param e The given evas.
* @return The created evas_gl object.
*/
EAPI Evas_GL *
evas_gl_new(Evas *e)
{
Evas_GL *evas_gl;
evas_gl = calloc(1, sizeof(Evas_GL));
if (!evas_gl) return NULL;
evas_gl->magic = MAGIC_EVAS_GL;
evas_gl->evas = e;
return evas_gl;
}
/**
* Frees the created Evas_GL object.
*
* @param evas_gl The given Evas_GL object.
*/
EAPI void
evas_gl_free(Evas_GL *evas_gl)
{
// Magic
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return;
MAGIC_CHECK_END();
free(evas_gl);
evas_gl = NULL;
}
/**
* Creates and returns new Evas_GL_Surface object for GL Rendering.
*
* @param evas_gl The given Evas_GL object.
* @param config The pixel format and configuration of the rendering surface.
* @param width The width of the surface.
* @param height The height of the surface.
* @return The created GL surface object.
*/
EAPI Evas_GL_Surface *
evas_gl_surface_create(Evas_GL *evas_gl, Evas_GL_Config *config, int width, int height)
{
Evas_GL_Surface *surf;
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return NULL;
MAGIC_CHECK_END();
surf = calloc(1, sizeof(Evas_GL_Surface));
surf->data = evas_gl->evas->engine.func->gl_surface_create(evas_gl->evas->engine.data.output, config, width, height);
if (!surf->data)
{
printf("Error: Failed creating a surface from the engine\n");
free(surf);
return NULL;
}
return surf;
}
/**
* Destroys the created Evas GL Surface.
*
* @param evas_gl The given Evas_GL object.
* @param surf The given GL surface object.
*/
EAPI void
evas_gl_surface_destroy(Evas_GL *evas_gl, Evas_GL_Surface *surf)
{
// Magic
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return;
MAGIC_CHECK_END();
if (!surf)
{
ERR("Trying to destroy a NULL surface pointer!\n");
return;
}
// Call Engine's Surface Destroy
evas_gl->evas->engine.func->gl_surface_destroy(evas_gl->evas->engine.data.output, surf->data);
free(surf);
surf = NULL;
}
/**
* Creates and returns a new Evas GL context object
*
* @param evas_gl The given Evas_GL object.
*/
EAPI Evas_GL_Context *
evas_gl_context_create(Evas_GL *evas_gl, Evas_GL_Context *share_ctx)
{
Evas_GL_Context *ctx;
// Magic
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return NULL;
MAGIC_CHECK_END();
// Allocate a context object
ctx = calloc(1, sizeof(Evas_GL_Context));
if (!ctx)
{
printf("Error: Unable to create a Evas_GL_Context object\n");
return NULL;
}
// Call engine->gl_create_context
if (share_ctx)
{
ctx->data = evas_gl->evas->engine.func->gl_context_create(evas_gl->evas->engine.data.output, share_ctx->data);
}
else
{
ctx->data = evas_gl->evas->engine.func->gl_context_create(evas_gl->evas->engine.data.output, NULL);
}
// Set a few variables
if (!ctx->data)
{
printf("Error: Failed creating a context from the engine\n");
free(ctx);
return NULL;
}
return ctx;
}
/**
* Destroys the given Evas GL context object
*
* @param evas_gl The given Evas_GL object.
* @param ctx The given Evas GL context.
*/
EAPI void
evas_gl_context_destroy(Evas_GL *evas_gl, Evas_GL_Context *ctx)
{
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return;
MAGIC_CHECK_END();
if (!ctx)
{
ERR("Trying to destroy a NULL context pointer!\n");
return;
}
evas_gl->evas->engine.func->gl_context_destroy(evas_gl->evas->engine.data.output, ctx->data);
free(ctx);
ctx = NULL;
}
/**
* Sets the given context as a current context for the given surface
*
* @param evas_gl The given Evas_GL object.
* @param surf The given Evas GL surface.
* @param ctx The given Evas GL context.
*/
EAPI Eina_Bool
evas_gl_make_current(Evas_GL *evas_gl, Evas_GL_Surface *surf, Evas_GL_Context *ctx)
{
Eina_Bool ret;
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return EINA_FALSE;
MAGIC_CHECK_END();
if ((!surf) || (!ctx))
ret = (Eina_Bool)evas_gl->evas->engine.func->gl_make_current(evas_gl->evas->engine.data.output, NULL, NULL);
else
ret = (Eina_Bool)evas_gl->evas->engine.func->gl_make_current(evas_gl->evas->engine.data.output, surf->data, ctx->data);
return ret;
}
/**
* Returns a GL or the Glue Layer's extension function.
*
* @param evas_gl The given Evas_GL object.
* @param name The name of the function to return.
*/
EAPI Evas_GL_Func
evas_gl_proc_address_get(Evas_GL *evas_gl, const char *name)
{
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return EINA_FALSE;
MAGIC_CHECK_END();
return (Evas_GL_Func)evas_gl->evas->engine.func->gl_proc_address_get(evas_gl->evas->engine.data.output, name);
}
/**
* Fills in the Native Surface information from the given Evas GL surface.
*
* @param evas_gl The given Evas_GL object.
* @param surf The given Evas GL surface to retrieve the Native Surface info from.
* @param ns The native surface structure that the function fills in.
*/
EAPI Eina_Bool
evas_gl_native_surface_get (Evas_GL *evas_gl, Evas_GL_Surface *surf, Evas_Native_Surface *ns)
{
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return EINA_FALSE;
MAGIC_CHECK_END();
return (Eina_Bool)evas_gl->evas->engine.func->gl_native_surface_get(evas_gl->evas->engine.data.output, surf->data, ns);
}
/**
* @}
*/
/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
/**
* 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;
void key_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
Evas_Event_Key_Down *ev;
ev = (Evas_Event_Key_Down *)event_info;
printf("You hit key: %s\n", ev->keyname);
ecore_main_loop_quit();
}
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, "Evas_GL Sample Program");
ecore_evas_borderless_set(ee, 0);
ecore_evas_show(ee);
canvas = ecore_evas_get(ee);
// Draw GL
init_gl(canvas);
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);
evas_object_focus_set(r1, 1);
evas_object_event_callback_add(r1, EVAS_CALLBACK_KEY_DOWN, key_down, NULL);
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;
// Evas GL code...
evasgl = evas_gl_new(evas);
sfc = evas_gl_surface_create(evasgl, &config, w, h);
ctx = evas_gl_context_create(evasgl, NULL);
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()
{
// 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 :*/
------------------------------------------------------------------------------
What You Don't Know About Data Connectivity CAN Hurt You
This paper provides an overview of data connectivity, details
its effect on application quality, and explores various alternative
solutions. http://p.sf.net/sfu/progress-d2d
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel