Evas GL: Add API evas_gl_error_get()

Similar in meaning to eglGetError()

@feature
This commit is contained in:
Jean-Philippe Andre 2014-09-01 18:11:53 +09:00
parent 08889de92b
commit 8d6f873354
7 changed files with 315 additions and 35 deletions

View File

@ -436,8 +436,8 @@ typedef enum _Evas_GL_Options_Bits
typedef enum _Evas_GL_Multisample_Bits
{
EVAS_GL_MULTISAMPLE_NONE = 0, /**< No multisample rendering */
EVAS_GL_MULTISAMPLE_LOW = 1, /**< MSAA with mininum number of samples */
EVAS_GL_MULTISAMPLE_MED = 2, /**< MSAA with half the number of max samples */
EVAS_GL_MULTISAMPLE_LOW = 1, /**< MSAA with minimum number of samples */
EVAS_GL_MULTISAMPLE_MED = 2, /**< MSAA with half the maximum number of samples */
EVAS_GL_MULTISAMPLE_HIGH = 3 /**< MSAA with maximum allowed samples */
} Evas_GL_Multisample_Bits;
@ -455,6 +455,7 @@ struct _Evas_GL_Config
Evas_GL_Multisample_Bits multisample_bits; /**< Optional Surface MSAA Bits */
};
/** @brief Constant to use when calling @ref evas_gl_string_query to retrieve the available Evas_GL extensions. */
#define EVAS_GL_EXTENSIONS 1
@ -575,6 +576,26 @@ EAPI Eina_Bool evas_gl_native_surface_get (Evas_GL *evas_gl, Evas
*/
EAPI Evas_GL_API *evas_gl_api_get (Evas_GL *evas_gl) EINA_ARG_NONNULL(1);
/**
* @brief Returns the last error of any evas_gl function called in the current thread.
* Initially, the error is set to @ref EVAS_GL_SUCCESS. A call to @ref evas_gl_error_get
* resets the error to @ref EVAS_GL_SUCCESS.
*
* @param[in] evas_gl The given Evas_GL object
*
* @return @ref EVAS_GL_SUCCESS in case of no error, or any other @c EVAS_GL error code.
*
* Since Evas GL is a glue layer for GL imitating EGL, the error codes returned
* have the same meaning as those defined in EGL.
*
* @note At the moment of writing, this API is only partially implemented
* and might return @c EVAS_GL_SUCCESS even when the last call(s) to
* Evas_GL failed.
*
* @since 1.12
*/
EAPI int evas_gl_error_get (Evas_GL *evas_gl) EINA_ARG_NONNULL(1);
#if !defined(__gl_h_) && !defined(__gl2_h_)
# define __gl_h_
# define __gl2_h_
@ -1299,6 +1320,40 @@ typedef signed long int GLsizeiptr; // Changed khronos_ssize_t
# endif
#endif
/**
* @name Evas GL error codes
*
* These are the possible return values of @ref evas_gl_error_get.
* The values are the same as EGL error codes - @c EGL_SUCCESS.
*
* Some of the values may be set directly by Evas GL when an obvious error was
* detected (eg. @c NULL pointers or invalid dimensions), otherwise Evas GL will
* call the backend's GetError() function and translate to a valid @c EVAS_GL_
* error code.
*
* @since 1.12
*
* @{
*/
#define EVAS_GL_SUCCESS 0x0000 /**< The last evas_gl_ operation succeeded. A call to @c evas_gl_error_get() will reset the error. */
#define EVAS_GL_NOT_INITIALIZED 0x0001 /**< Evas GL was not initialized or a @c NULL pointer was passed */
#define EVAS_GL_BAD_ACCESS 0x0002 /**< Bad access; for more information, please refer to its EGL counterpart */
#define EVAS_GL_BAD_ALLOC 0x0003 /**< Bad allocation; for more information, please refer to its EGL counterpart */
#define EVAS_GL_BAD_ATTRIBUTE 0x0004 /**< Bad attribute; for more information, please refer to its EGL counterpart */
#define EVAS_GL_BAD_CONFIG 0x0005 /**< Bad configuration; for more information, please refer to its EGL counterpart */
#define EVAS_GL_BAD_CONTEXT 0x0006 /**< Bad context; for more information, please refer to its EGL counterpart */
#define EVAS_GL_BAD_CURRENT_SURFACE 0x0007 /**< Bad current surface; for more information, please refer to its EGL counterpart */
#define EVAS_GL_BAD_DISPLAY 0x0008 /**< Bad display; for more information, please refer to its EGL counterpart */
#define EVAS_GL_BAD_MATCH 0x0009 /**< Bad match; for more information, please refer to its EGL counterpart */
#define EVAS_GL_BAD_NATIVE_PIXMAP 0x000A /**< Bad native pixmap; for more information, please refer to its EGL counterpart */
#define EVAS_GL_BAD_NATIVE_WINDOW 0x000B /**< Bad native window; for more information, please refer to its EGL counterpart */
#define EVAS_GL_BAD_PARAMETER 0x000C /**< Bad parameter; for more information, please refer to its EGL counterpart */
#define EVAS_GL_BAD_SURFACE 0x000D /**< Bad surface; for more information, please refer to its EGL counterpart */
/* EGL 1.1 - IMG_power_management */
#define EVAS_GL_CONTEXT_LOST 0x000E /**< Context lost; for more information, please refer to its EGL counterpart */
/** @} */
#define EVAS_GL_API_VERSION 1
struct _Evas_GL_API
{

View File

@ -3,6 +3,8 @@
#include "evas_private.h"
#include "Evas_GL.h"
typedef struct _Evas_GL_TLS_data Evas_GL_TLS_data;
struct _Evas_GL
{
DATA32 magic;
@ -11,6 +13,8 @@ struct _Evas_GL
Eina_List *contexts;
Eina_List *surfaces;
Eina_Lock lck;
Eina_TLS resource_key;
Eina_List *resource_list;
};
struct _Evas_GL_Context
@ -23,6 +27,95 @@ struct _Evas_GL_Surface
void *data;
};
struct _Evas_GL_TLS_data
{
int error_state;
};
Evas_GL_TLS_data *
_evas_gl_internal_tls_get(Evas_GL *evas_gl)
{
Evas_GL_TLS_data *tls_data;
if (!evas_gl) return NULL;
if (!(tls_data = eina_tls_get(evas_gl->resource_key)))
{
tls_data = (Evas_GL_TLS_data*) calloc(1, sizeof(Evas_GL_TLS_data));
if (!tls_data)
{
ERR("Evas_GL: Could not set error!");
return NULL;
}
tls_data->error_state = EVAS_GL_SUCCESS;
if (eina_tls_set(evas_gl->resource_key, (void*)tls_data) == EINA_TRUE)
{
LKL(evas_gl->lck);
evas_gl->resource_list = eina_list_prepend(evas_gl->resource_list, tls_data);
LKU(evas_gl->lck);
return tls_data;
}
else
{
ERR("Evas_GL: Failed setting TLS data!");
free(tls_data);
return NULL;
}
}
return tls_data;
}
void
_evas_gl_internal_tls_destroy(Evas_GL *evas_gl)
{
Evas_GL_TLS_data *tls_data;
if (!evas_gl) return;
if (!(tls_data = eina_tls_get(evas_gl->resource_key)))
{
WRN("Destructor: TLS data was never set!");
return;
}
LKL(evas_gl->lck);
EINA_LIST_FREE(evas_gl->resource_list, tls_data)
free(tls_data);
if (evas_gl->resource_key)
eina_tls_free(evas_gl->resource_key);
evas_gl->resource_key = 0;
LKU(evas_gl->lck);
}
void
_evas_gl_internal_error_set(Evas_GL *evas_gl, int error_enum)
{
Evas_GL_TLS_data *tls_data;
if (!evas_gl) return;
tls_data = _evas_gl_internal_tls_get(evas_gl);
if (!tls_data) return;
tls_data->error_state = error_enum;
}
int
_evas_gl_internal_error_get(Evas_GL *evas_gl)
{
Evas_GL_TLS_data *tls_data;
if (!evas_gl) return EVAS_GL_NOT_INITIALIZED;
tls_data = _evas_gl_internal_tls_get(evas_gl);
if (!tls_data) return EVAS_GL_NOT_INITIALIZED;
return tls_data->error_state;
}
EAPI Evas_GL *
evas_gl_new(Evas *e)
{
@ -46,6 +139,15 @@ evas_gl_new(Evas *e)
return NULL;
}
// Initialize tls resource key
if (eina_tls_new(&(evas_gl->resource_key)) == EINA_FALSE)
{
ERR("Error creating tls key");
free(evas_gl);
return NULL;
}
_evas_gl_internal_error_set(evas_gl, EVAS_GL_SUCCESS);
return evas_gl;
}
@ -64,6 +166,9 @@ evas_gl_free(Evas_GL *evas_gl)
while (evas_gl->contexts)
evas_gl_context_destroy(evas_gl, evas_gl->contexts->data);
// Destroy tls
_evas_gl_internal_tls_destroy(evas_gl);
eo_data_unref(evas_gl->evas->evas, evas_gl->evas);
evas_gl->magic = 0;
LKD(evas_gl->lck);
@ -100,18 +205,24 @@ evas_gl_surface_create(Evas_GL *evas_gl, Evas_GL_Config *config, int width, int
if (!config)
{
ERR("Invalid Config Pointer!");
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_CONFIG);
return NULL;
}
if ((width <= 0) || (height <= 0))
{
ERR("Invalid surface dimensions: %d, %d", width, height);
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_PARAMETER);
return NULL;
}
surf = calloc(1, sizeof(Evas_GL_Surface));
if (!surf) return NULL;
if (!surf)
{
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_ALLOC);
return NULL;
}
surf->data = evas_gl->evas->engine.func->gl_surface_create(evas_gl->evas->engine.data.output, config, width, height);
@ -141,6 +252,7 @@ evas_gl_surface_destroy(Evas_GL *evas_gl, Evas_GL_Surface *surf)
if (!surf)
{
ERR("Trying to destroy a NULL surface pointer!");
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_SURFACE);
return;
}
@ -172,6 +284,7 @@ evas_gl_context_create(Evas_GL *evas_gl, Evas_GL_Context *share_ctx)
if (!ctx)
{
ERR("Unable to create a Evas_GL_Context object");
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_ALLOC);
return NULL;
}
@ -199,7 +312,6 @@ evas_gl_context_create(Evas_GL *evas_gl, Evas_GL_Context *share_ctx)
LKU(evas_gl->lck);
return ctx;
}
EAPI void
@ -213,6 +325,7 @@ evas_gl_context_destroy(Evas_GL *evas_gl, Evas_GL_Context *ctx)
if (!ctx)
{
ERR("Trying to destroy a NULL context pointer!");
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_CONTEXT);
return;
}
@ -245,6 +358,7 @@ evas_gl_make_current(Evas_GL *evas_gl, Evas_GL_Surface *surf, Evas_GL_Context *c
else
{
ERR("Bad match between surface: %p and context: %p", surf, ctx);
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_MATCH);
return EINA_FALSE;
}
@ -281,12 +395,14 @@ evas_gl_native_surface_get(Evas_GL *evas_gl, Evas_GL_Surface *surf, Evas_Native_
if (!surf)
{
ERR("Invalid surface!");
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_SURFACE);
return EINA_FALSE;
}
if (!ns)
{
ERR("Invalid input parameters!");
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_PARAMETER);
return EINA_FALSE;
}
@ -303,3 +419,25 @@ evas_gl_api_get(Evas_GL *evas_gl)
return (Evas_GL_API*)evas_gl->evas->engine.func->gl_api_get(evas_gl->evas->engine.data.output);
}
EAPI int
evas_gl_error_get(Evas_GL *evas_gl)
{
int err;
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return EVAS_GL_NOT_INITIALIZED;
MAGIC_CHECK_END();
if ((err = _evas_gl_internal_error_get(evas_gl)) != EVAS_GL_SUCCESS) goto end;
if (!evas_gl->evas->engine.func->gl_error_get)
err = EVAS_GL_NOT_INITIALIZED;
else
err = evas_gl->evas->engine.func->gl_error_get(evas_gl->evas->engine.data.output);
end:
/* Call to evas_gl_error_get() should set error to EVAS_GL_SUCCESS */
_evas_gl_internal_error_set(evas_gl, EVAS_GL_SUCCESS);
return err;
}

View File

@ -1244,6 +1244,7 @@ struct _Evas_Func
Eina_Bool (*gl_surface_lock) (void *data, void *surface);
Eina_Bool (*gl_surface_read_pixels) (void *data, void *surface, int x, int y, int w, int h, Evas_Colorspace cspace, void *pixels);
Eina_Bool (*gl_surface_unlock) (void *data, void *surface);
int (*gl_error_get) (void *data);
int (*image_load_error_get) (void *data, void *image);
int (*font_run_end_get) (void *data, Evas_Font_Set *font, Evas_Font_Instance **script_fi, Evas_Font_Instance **cur_fi, Evas_Script_Type script, const Eina_Unicode *text, int run_len);

View File

@ -63,61 +63,95 @@ char _gl_ext_string[10240] = { 0 };
// Evas extensions from EGL extensions
#ifdef GL_GLES
static void *
evgl_evasglCreateImage(int target, void* buffer, int *attrib_list)
#define EGLDISPLAY_GET() _evgl_egl_display_get(__FUNCTION__)
static EGLDisplay
_evgl_egl_display_get(const char *function)
{
EGLDisplay dpy = EGL_NO_DISPLAY;
EVGL_Resource *rsc;
if (!(rsc=_evgl_tls_resource_get()))
{
ERR("Unable to execute GL command. Error retrieving tls");
return NULL;
ERR("%s: Unable to execute GL command. Error retrieving tls", function);
_evgl_error_set(EVAS_GL_NOT_INITIALIZED);
return EGL_NO_DISPLAY;
}
if (!rsc->current_eng)
{
ERR("Unable to retrive Current Engine");
return NULL;
ERR("%s: Unable to retrive Current Engine", function);
_evgl_error_set(EVAS_GL_NOT_INITIALIZED);
return EGL_NO_DISPLAY;
}
if ((evgl_engine) && (evgl_engine->funcs->display_get))
{
dpy = (EGLDisplay)evgl_engine->funcs->display_get(rsc->current_eng);
return EXT_FUNC(eglCreateImage)(dpy, EGL_NO_CONTEXT, target, buffer, attrib_list);
return dpy;
}
else
{
ERR("Invalid Engine... (Can't acccess EGL Display)\n");
return NULL;
ERR("%s: Invalid Engine... (Can't acccess EGL Display)\n", function);
_evgl_error_set(EVAS_GL_BAD_DISPLAY);
return EGL_NO_DISPLAY;
}
}
static void *
_evgl_eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx,
int target, void* buffer, const int *attrib_list)
{
int *attribs = NULL;
/* Convert 0 terminator into a EGL_NONE terminator */
if (attrib_list)
{
int cnt = 0;
int *a;
for (a = (int *) attrib_list; (*a) && (*a != EGL_NONE); a += 2)
{
/* TODO: Verify supported attributes */
cnt += 2;
}
attribs = alloca(sizeof(int) * (cnt + 1));
for (a = attribs; (*attrib_list) && (*attrib_list != EGL_NONE);
a += 2, attrib_list += 2)
{
a[0] = attrib_list[0];
a[1] = attrib_list[1];
}
*a = EGL_NONE;
}
return EXT_FUNC(eglCreateImage)(dpy, ctx, target, buffer, attribs);
}
static void *
evgl_evasglCreateImage(int target, void* buffer, const int *attrib_list)
{
EGLDisplay dpy = EGLDISPLAY_GET();
EGLContext ctx = EGL_NO_CONTEXT;
if (!dpy) return NULL;
/* EGL_NO_CONTEXT will always fail for TEXTURE_2D */
if (target == EVAS_GL_TEXTURE_2D)
{
ctx = eglGetCurrentContext();
INF("Creating EGL image based on the current context: %p", ctx);
}
return _evgl_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
}
static void
evgl_evasglDestroyImage(EvasGLImage image)
{
EGLDisplay dpy = EGL_NO_DISPLAY;
EVGL_Resource *rsc;
if (!(rsc=_evgl_tls_resource_get()))
{
ERR("Unable to execute GL command. Error retrieving tls");
return;
}
if (!rsc->current_eng)
{
ERR("Unable to retrive Current Engine");
return;
}
if ((evgl_engine) && (evgl_engine->funcs->display_get))
{
dpy = (EGLDisplay)evgl_engine->funcs->display_get(rsc->current_eng);
EXT_FUNC(eglDestroyImage)(dpy, image);
}
else
ERR("Invalid Engine... (Can't acccess EGL Display)\n");
EGLDisplay dpy = EGLDISPLAY_GET();
if (!dpy) return;
EXT_FUNC(eglDestroyImage)(dpy, image);
}
static void

View File

@ -66,6 +66,8 @@ _internal_resources_create(void *eng_data)
goto error;
}
rsc->error_state = EVAS_GL_SUCCESS;
return rsc;
error:
@ -1270,6 +1272,34 @@ _evgl_direct_enabled()
return _evgl_direct_renderable(rsc, sfc);
}
void
_evgl_error_set(int error_enum)
{
EVGL_Resource *rsc;
if (!(rsc=_evgl_tls_resource_get()))
{
WRN("evgl: Unable to set error!");
return;
}
rsc->error_state = error_enum;
}
int
_evgl_error_get()
{
EVGL_Resource *rsc;
if (!(rsc=_evgl_tls_resource_get()))
{
WRN("evgl: Unable to get error!");
return EVAS_GL_NOT_INITIALIZED;
}
return rsc->error_state;
}
//---------------------------------------------------------------//
// Exported functions for evas_engine to use
@ -1428,12 +1458,14 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
if (!evgl_engine)
{
ERR("Invalid EVGL Engine!");
_evgl_error_set(EVAS_GL_BAD_ACCESS);
return NULL;
}
if (!cfg)
{
ERR("Invalid Config!");
_evgl_error_set(EVAS_GL_BAD_CONFIG);
return NULL;
}
@ -1442,6 +1474,7 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
{
ERR("Requested surface size [%d, %d] is greater than max supported size [%d, %d]",
w, h, evgl_engine->caps.max_w, evgl_engine->caps.max_h);
_evgl_error_set(EVAS_GL_BAD_PARAMETER);
return NULL;
}
@ -1469,6 +1502,7 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
if (!sfc)
{
ERR("Surface allocation failed.");
_evgl_error_set(EVAS_GL_BAD_ALLOC);
goto error;
}
@ -1480,6 +1514,7 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
if (!_internal_config_set(sfc, cfg))
{
ERR("Unsupported Format!");
_evgl_error_set(EVAS_GL_BAD_CONFIG);
goto error;
}
@ -1487,6 +1522,7 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
if (!_internal_resource_make_current(eng_data, NULL))
{
ERR("Error doing an internal resource make current");
_evgl_error_set(EVAS_GL_BAD_CONTEXT);
goto error;
}
@ -1494,6 +1530,7 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
if (!_surface_buffers_create(sfc))
{
ERR("Unable Create Specificed Surfaces.");
_evgl_error_set(EVAS_GL_BAD_ALLOC);
goto error;
};
@ -1503,6 +1540,7 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 0))
{
ERR("Unable Create Allocate Memory for Surface.");
_evgl_error_set(EVAS_GL_BAD_ALLOC);
goto error;
}
}
@ -1510,6 +1548,7 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
if (!evgl_engine->funcs->make_current(eng_data, NULL, NULL, 0))
{
ERR("Error doing make_current(NULL, NULL).");
_evgl_error_set(EVAS_GL_BAD_CONTEXT);
goto error;
}
@ -1601,6 +1640,7 @@ evgl_context_create(void *eng_data, EVGL_Context *share_ctx)
if (!evgl_engine)
{
ERR("Invalid EVGL Engine!");
_evgl_error_set(EVAS_GL_BAD_ACCESS);
return NULL;
}
@ -1609,6 +1649,7 @@ evgl_context_create(void *eng_data, EVGL_Context *share_ctx)
if (!ctx)
{
ERR("Error allocating context object.");
_evgl_error_set(EVAS_GL_BAD_ALLOC);
return NULL;
}
@ -1694,6 +1735,8 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
(sfc && (!ctx)) )
{
ERR("Invalid Inputs. Engine: %p Surface: %p Context: %p!", evgl_engine, sfc, ctx);
if(!sfc) _evgl_error_set(EVAS_GL_BAD_SURFACE);
if(!ctx) _evgl_error_set(EVAS_GL_BAD_CONTEXT);
return 0;
}
@ -1743,6 +1786,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
if (!_surface_buffers_allocate(eng_data, sfc, 0, 0, 1))
{
ERR("Unable to destroy surface buffers!");
_evgl_error_set(EVAS_GL_BAD_ALLOC);
return 0;
}
sfc->buffers_allocated = 0;
@ -1762,6 +1806,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 1))
{
ERR("Unable Create Specificed Surfaces. Unsupported format!");
_evgl_error_set(EVAS_GL_BAD_ALLOC);
return 0;
};
sfc->buffers_allocated = 1;
@ -1774,6 +1819,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
if (!_internal_resource_make_current(eng_data, ctx))
{
ERR("Error doing a make current with internal surface. Context: %p", ctx);
_evgl_error_set(EVAS_GL_BAD_CONTEXT);
return 0;
}
@ -1828,6 +1874,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
if (!_surface_buffers_fbo_set(sfc, ctx->surface_fbo))
{
ERR("Attaching buffers to context fbo failed. Engine: %p Surface: %p Context FBO: %u", evgl_engine, sfc, ctx->surface_fbo);
_evgl_error_set(EVAS_GL_BAD_CONTEXT);
return 0;
}
}

View File

@ -212,6 +212,8 @@ struct _EVGL_Resource
EVGL_Context *current_ctx;
void *current_eng;
int error_state;
struct {
EVGLNative_Surface surface;
int rendered;
@ -286,5 +288,7 @@ extern void _evgl_tls_resource_destroy(void *data);
extern EVGL_Context *_evgl_current_context_get();
extern int _evgl_not_in_pixel_get();
extern int _evgl_direct_enabled();
extern void _evgl_error_set(int error_enum);
extern int _evgl_error_get();
#endif //_EVAS_GL_CORE_PRIVATE_H

View File

@ -3002,6 +3002,7 @@ static Evas_Func func =
NULL, // need software mesa for gl rendering <- gl_surface_lock
NULL, // need software mesa for gl rendering <- gl_surface_read_pixels
NULL, // need software mesa for gl rendering <- gl_surface_unlock
NULL, // need software mesa for gl rendering <- gl_error_get
eng_image_load_error_get,
eng_font_run_font_end_get,
eng_image_animated_get,