Mercurial > MadButterfly
view src/graph_engine_openvg.c @ 1532:4a92b639a1cd
Clear selection set when switching current scene.
To clear selection set after switching away from current to another scene.
It avoids Inkscape select on nodes they are not saw after switching.
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Fri, 30 Sep 2011 12:31:33 +0800 |
parents | baf4c4d48cff |
children |
line wrap: on
line source
#include "mb_graph_engine_openvg.h" #include "mb_tools.h" EGLNativeDisplayType _ge_openvg_disp_id = EGL_DEFAULT_DISPLAY; mbe_t *_ge_openvg_current_canvas = NULL; #ifndef ASSERT #define ASSERT(x) #endif #ifndef ERR #include <stdio.h> #include <stdlib.h> #define ERR(msg) do { fprintf(stderr, __FILE__ ":%d: %s", __LINE__, msg); abort(); } while(0) #endif #ifndef NOT_IMPLEMENT #define NOT_IMPLEMENT(func) \ ERR(func " is not impmemented\n") #endif #define MK_ID(mtx) \ do { \ (mtx)[0] = 1; \ (mtx)[1] = 0; \ (mtx)[2] = 0; \ (mtx)[3] = 0; \ (mtx)[4] = 1; \ (mtx)[5] = 0; \ (mtx)[6] = 0; \ (mtx)[7] = 0; \ (mtx)[8] = 1; \ } while(0) #define VG_MBE_EGLSURFACE(mbe) ((EGLSurface *)(mbe)->tgt->surface) /*! \brief Information associated with VGImage. * * A VGImage can associated one of pattern or surface. This type is * used to make sure previous associated pattern or surface being * released before new association. * * A _ge_openvg_img can be associated by mutltiple patterns and * surfaces. But, at most one of associated patterns or surfaces, the * _ge_openvg_img can be activated for at any instant. * _ge_openvg_img::activated_for trace the object it being activated * for. When a context will be current, the _ge_openvg_img associated * with its surface would be activated for the surface. When a paint * wil be used, the _ge_openvg_img associated must be activated for * the paint. Before activated, the old activation must be * deactivated. _ge_openvg_img::deactivate_func is a pointer to * deactivation function of activated pattern or surface. * * \sa _ge_openvg_img_t * \note This is type is for internal using of OpenVG graphic engine. */ struct _ge_openvg_img { int ref; VGImage img; void *activated_for; void (*deactivate_func)(void *obj); }; #define SURFACE_VG_IMG(surface) ((surface)->tgt->asso_img->img) static EGLContext init_ctx; /*! \brief Convert mb_img_fmt_t to VGImageFormat */ static VGImageFormat _mb_ifmt_2_vgifmt(mb_img_fmt_t fmt) { VGImageFormat vgifmt; switch(fmt) { case MB_IFMT_ARGB32: vgifmt = VG_sARGB_8888; break; case MB_IFMT_RGB24: vgifmt = -1; break; case MB_IFMT_A8: vgifmt = VG_A_8; break; case MB_IFMT_A1: vgifmt = -1; break; case MB_IFMT_RGB16_565: vgifmt = VG_sRGB_565; break; default: return -1; } return vgifmt; } /*! \brief create image object for OpenVG */ static _ge_openvg_img_t * _alloc_vgimage(mb_img_fmt_t fmt, int w, int h) { VGImage vg_img; VGImageFormat vgifmt; _ge_openvg_img_t *ge_img; vgifmt = _mb_ifmt_2_vgifmt(fmt); if(vgifmt == -1) return NULL; vg_img = vgCreateImage(vgifmt, w, h, VG_IMAGE_QUALITY_NONANTIALIASED); if(vg_img == VG_INVALID_HANDLE) return NULL; ge_img = O_ALLOC(_ge_openvg_img_t); if(ge_img == NULL) { vgDestroyImage(vg_img); return NULL; } ge_img->ref = 1; ge_img->img = vg_img; ge_img->activated_for = NULL; ge_img->deactivate_func = NULL; return ge_img; } /*! \brief Free image object for OpenVG */ static void _free_vgimage(_ge_openvg_img_t *ge_img) { if(--ge_img->ref > 0) { if(ge_img->activated_for) { ge_img->deactivate_func(ge_img->activated_for); ge_img->activated_for = NULL; } return; } vgDestroyImage(ge_img->img); free(ge_img); } static void _ge_vg_img_deactivate_for_pattern(void *obj) { mbe_pattern_t *ptn = (mbe_pattern_t *)obj; VGPaint vg_paint; vg_paint = ptn->paint; vgPaintPattern(vg_paint, VG_INVALID_HANDLE); } /*! \brief Activate a VGImage for a pattern paint. * * \sa _ge_openvg_img */ void _ge_vg_img_activate_for_pattern(mbe_pattern_t *ptn) { _ge_openvg_img_t *ge_img; VGPaint vg_paint; VGImage vg_img; ge_img = ptn->asso_img; if(ge_img == NULL) return; if(ge_img->activated_for == (void *)ptn) return; if(ge_img->activated_for) ge_img->deactivate_func(ge_img->activated_for); ge_img->activated_for = ptn; ge_img->deactivate_func = _ge_vg_img_deactivate_for_pattern; vg_img = ge_img->img; vg_paint = ptn->paint; vgPaintPattern(vg_paint, vg_img); } /*! \brief Deactivate a VGImage for a VGSurface. * * A VGImage can not deatached from VGSurface. But, it is not clear * in the document of EGL. We assume that a VGImage can be used as * pattern of a paint, once associated surface is not current * rendering context. */ static void _ge_vg_img_deactivate_for_surface(void *obj) { /* NOT_IMPLEMENT("_ge_vg_img_deactivate_for_surface"); */ } /*! \brief Activate a VGImage for a surface * * \sa _ge_openvg_img */ void _ge_vg_img_activate_for_surface(mbe_surface_t *surf) { _ge_openvg_img_t *ge_img; ge_img = surf->asso_img; if(ge_img == NULL) return; if(ge_img->activated_for == (void *)surf) return; if(ge_img->activated_for) ge_img->deactivate_func(ge_img->activated_for); ge_img->activated_for = surf; ge_img->deactivate_func = _ge_vg_img_deactivate_for_surface; } /* * This implementation supports only from image surface. */ mbe_pattern_t * mbe_pattern_create_for_surface(mbe_surface_t *surface) { mbe_pattern_t *pattern; _ge_openvg_img_t *ge_img; VGfloat *mtx; VGPaint paint; /* Support only from image surface */ if(surface->asso_img == NULL) return NULL; paint = vgCreatePaint(); if(paint == VG_INVALID_HANDLE) return NULL; ge_img = surface->asso_img; pattern = O_ALLOC(mbe_pattern_t); pattern->asso_img = ge_img; ge_img->ref++; /* increase reference count */ pattern->paint = paint; mtx = pattern->mtx; MK_ID(mtx); return pattern; } void _mbe_load_pattern_mtx(VGfloat *mtx1, VGfloat *mtx2, int mode) { VGfloat affine; vgSeti(VG_MATRIX_MODE, mode); vgLoadMatrix(mtx1); if(mtx2) vgMultMatrix(mtx2); } static mbe_pattern_t * _mbe_pattern_create_gradient(VGfloat *gradient, int grad_len, int grad_type, grad_stop_t *stops, int stop_cnt) { VGPaint paint; mbe_pattern_t *pattern; static VGfloat *ov_stops = 0; static int max_stop_cnt = 0; VGfloat *cur_ov_stop; grad_stop_t *cur_stop; int i; /* Make sure there is enough space */ if(max_stop_cnt < stop_cnt) { max_stop_cnt = (stop_cnt + 0xf) & ~0xf; cur_ov_stop = (VGfloat *)realloc(ov_stops, max_stop_cnt * sizeof(VGfloat) * 5); if(cur_ov_stop == NULL) { max_stop_cnt = 0; return NULL; } ov_stops = cur_ov_stop; } cur_ov_stop = ov_stops; cur_stop = stops; for(i = 0; i < stop_cnt; i++) { *cur_ov_stop++ = cur_stop->offset; *cur_ov_stop++ = cur_stop->r; *cur_ov_stop++ = cur_stop->g; *cur_ov_stop++ = cur_stop->b; *cur_ov_stop++ = cur_stop->a; cur_stop++; } paint = vgCreatePaint(); if(paint == VG_INVALID_HANDLE) return NULL; vgSetParameteri(paint, VG_PAINT_TYPE, grad_type); vgSetParameterfv(paint, VG_PAINT_RADIAL_GRADIENT, grad_len, gradient); vgSetParameterfv(paint, VG_PAINT_COLOR_RAMP_STOPS, 5 * stop_cnt, ov_stops); pattern = O_ALLOC(mbe_pattern_t); if(pattern == NULL) { vgDestroyPaint(paint); return NULL; } pattern->paint = paint; pattern->asso_img = NULL; MK_ID(pattern->mtx); return pattern; } /* * \note OpenVG does not support start circle, it supports only focal * point. It means radius0 is not working. */ mbe_pattern_t * mbe_pattern_create_radial(co_aix cx0, co_aix cy0, co_aix radius0, co_aix cx1, co_aix cy1, co_aix radius1, grad_stop_t *stops, int stop_cnt) { mbe_pattern_t *pattern; VGfloat gradient[] = {cx0, cy0, cx1, cy1, radius1}; pattern = _mbe_pattern_create_gradient(gradient, 5, VG_PAINT_TYPE_RADIAL_GRADIENT, stops, stop_cnt); return pattern; } mbe_pattern_t * mbe_pattern_create_linear(co_aix x0, co_aix y0, co_aix x1, co_aix y1, grad_stop_t *stops, int stop_cnt) { mbe_pattern_t *pattern; VGfloat gradient[] = {x0, y0, x1, y1}; pattern = _mbe_pattern_create_gradient(gradient, 4, VG_PAINT_TYPE_LINEAR_GRADIENT, stops, stop_cnt); return pattern; } mbe_pattern_t * mbe_pattern_create_image(mb_img_data_t *img) { VGPaint paint; mbe_pattern_t *pattern; _ge_openvg_img_t *ge_img; VGImage vg_img; VGImageFormat fmt = VG_sARGB_8888; /* \note OpenVG implementation supports one \ref MB_IFMT_ARGB32 * image. */ if(img->fmt != MB_IFMT_ARGB32) return NULL; /* Allocate objects */ ge_img = _alloc_vgimage(MB_IFMT_ARGB32, img->w, img->h); pattern = O_ALLOC(mbe_pattern_t); paint = vgCreatePaint(); if(ge_img == NULL || pattern == NULL || paint == VG_INVALID_HANDLE) goto err; /* Create and copy pixels into VGImage */ vg_img = ge_img->img; vgImageSubData(vg_img, img->content, img->stride, fmt, 0, 0, img->w, img->h); pattern->paint = paint; pattern->asso_img = ge_img; return pattern; err: if(ge_img) _free_vgimage(ge_img); if(pattern) free(pattern); if(paint != VG_INVALID_HANDLE) vgDestroyPaint(paint); vgDestroyImage(vg_img); return NULL; } void mbe_pattern_destroy(mbe_pattern_t *ptn) { if(ptn->asso_img) _free_vgimage(ptn->asso_img); vgDestroyPaint(ptn->paint); free(ptn); } void mbe_pattern_set_matrix(mbe_pattern_t *ptn, co_aix *mtx) { co_aix rev[6]; compute_reverse(mtx, rev); ptn->mtx[0] = rev[0]; ptn->mtx[1] = rev[3]; ptn->mtx[2] = 0; ptn->mtx[3] = rev[1]; ptn->mtx[4] = rev[4]; ptn->mtx[5] = 0; ptn->mtx[6] = rev[2]; ptn->mtx[7] = rev[5]; ptn->mtx[8] = 1; } void mbe_set_source_rgba(mbe_t *canvas, co_comp_t r, co_comp_t g, co_comp_t b, co_comp_t a) { VGPaint paint; VGuint color; VGfloat rgba[4]; paint = canvas->paint; if(paint == VG_INVALID_HANDLE || canvas->src != NULL) { /* previous one is not a color paint */ if(canvas->src) { mbe_pattern_destroy(canvas->src); canvas->src = NULL; } paint = vgCreatePaint(); ASSERT(paint != VG_INVALID_HANDLE); vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); canvas->paint = paint; } rgba[0] = r; rgba[1] = g; rgba[2] = b; rgba[3] = a; vgSetParameterfv(paint, VG_PAINT_COLOR, 4, rgba); canvas->paint_installed = 0; } void mbe_scissoring(mbe_t *canvas, int n_areas, area_t **areas) { static VGint *scissors = NULL; static int n_scissors = 0; VGint *coord; area_t *area; int i; _MK_CURRENT_CTX(canvas); if(n_areas > n_scissors) { if(scissors) free(scissors); n_scissors = (n_areas + 0xf) & ~0xf; scissors = (VGint *)malloc(sizeof(VGint) * n_scissors * 4); ASSERT(scissors != NULL); } coord = scissors; for(i = 0; i < n_areas; i++) { area = areas[i]; *coord++ = area->x; *coord++ = area->y; *coord++ = area->w; *coord++ = area->h; } vgSeti(VG_SCISSORING, VG_TRUE); vgSetiv(VG_SCISSOR_RECTS, n_areas * 4, scissors); } static int _openvg_find_config(mb_img_fmt_t fmt, int w, int h, EGLConfig *config) { EGLDisplay display; EGLint attrib_list[32]; EGLConfig configs[1]; EGLint nconfigs; int i = 0; EGLBoolean r; switch(fmt) { case MB_IFMT_ARGB32: attrib_list[i++] = EGL_RED_SIZE; attrib_list[i++] = 8; attrib_list[i++] = EGL_GREEN_SIZE; attrib_list[i++] = 8; attrib_list[i++] = EGL_BLUE_SIZE; attrib_list[i++] = 8; attrib_list[i++] = EGL_ALPHA_SIZE; attrib_list[i++] = 8; break; case MB_IFMT_RGB24: attrib_list[i++] = EGL_RED_SIZE; attrib_list[i++] = 8; attrib_list[i++] = EGL_GREEN_SIZE; attrib_list[i++] = 8; attrib_list[i++] = EGL_BLUE_SIZE; attrib_list[i++] = 8; break; case MB_IFMT_A8: attrib_list[i++] = EGL_ALPHA_SIZE; attrib_list[i++] = 8; break; case MB_IFMT_A1: attrib_list[i++] = EGL_ALPHA_SIZE; attrib_list[i++] = 1; break; case MB_IFMT_RGB16_565: attrib_list[i++] = EGL_RED_SIZE; attrib_list[i++] = 5; attrib_list[i++] = EGL_GREEN_SIZE; attrib_list[i++] = 6; attrib_list[i++] = EGL_BLUE_SIZE; attrib_list[i++] = 5; break; default: return -1; } attrib_list[i++] = EGL_SURFACE_TYPE; attrib_list[i++] = EGL_PBUFFER_BIT; #if 0 attrib_list[i++] = EGL_MAX_PBUFFER_WIDTH; attrib_list[i++] = w; attrib_list[i++] = EGL_MAX_PBUFFER_HEIGHT; attrib_list[i++] = h; #endif attrib_list[i++] = EGL_RENDERABLE_TYPE; attrib_list[i++] = EGL_OPENVG_BIT; attrib_list[i++] = EGL_NONE; display = _VG_DISPLAY(); r = eglChooseConfig(display, attrib_list, configs, 1, &nconfigs); if(!r) return -1; *config = configs[0]; return 0; } #ifdef EGL_GLX /*! \brief Create an EGL window surface for X11. * * This function is compiled only for GLX enabled. */ mbe_surface_t * mbe_win_surface_create(void *display, void *drawable, int fmt, int width, int height) { EGLDisplay egl_disp; EGLSurface egl_surface; mbe_surface_t *surface; EGLConfig config; EGLint attrib_list[2] = {EGL_NONE}; int r; r = _openvg_find_config(fmt, width, height, &config); if(r != 0) return NULL; egl_disp = eglGetDisplay((Display *)display); if(egl_disp == EGL_NO_DISPLAY || egl_disp != _VG_DISPLAY()) return NULL; egl_surface = eglCreateWindowSurface(egl_disp, config, (EGLNativeWindowType)drawable, attrib_list); surface = O_ALLOC(mbe_surface_t); if(surface == NULL) { eglDestroySurface(egl_disp, egl_surface); return NULL; } surface->surface = egl_surface; surface->asso_mbe = NULL; surface->asso_img = NULL; surface->fmt = fmt; return surface; } #endif mbe_surface_t * mbe_image_surface_create(mb_img_fmt_t fmt, int w, int h) { EGLSurface surface; EGLDisplay display; EGLConfig config; EGLint attrib_list[1] = {EGL_NONE}; _ge_openvg_img_t *ge_img; mbe_surface_t *mbe_surface; int r; r = _openvg_find_config(fmt, w, h, &config); if(r != 0) return NULL; ge_img = _alloc_vgimage(fmt, w, h); if(ge_img == NULL) return NULL; display = _VG_DISPLAY(); /* Some implementation does not support pbuffer. * We need use some other surface to replace this one. * * EGL does not support any attributes for pbuffer used by OpenVG. */ surface = eglCreatePbufferFromClientBuffer(display, EGL_OPENVG_IMAGE, (EGLClientBuffer)ge_img->img, config, attrib_list); if(surface == EGL_NO_SURFACE) { _free_vgimage(ge_img); return NULL; } mbe_surface = O_ALLOC(mbe_surface_t); if(mbe_surface == NULL) { _free_vgimage(ge_img); eglDestroySurface(display, surface); return NULL; } mbe_surface->surface = surface; mbe_surface->asso_mbe = NULL; mbe_surface->asso_img = ge_img; mbe_surface->w = w; mbe_surface->h = h; mbe_surface->fmt = fmt; return mbe_surface; } mbe_surface_t * mbe_image_surface_create_for_data(unsigned char *data, mb_img_fmt_t fmt, int width, int height, int stride) { NOT_IMPLEMENT("mbe_image_surface_create_for_data"); return NULL; } void mbe_surface_destroy(mbe_surface_t *surface) { EGLDisplay display; display = _VG_DISPLAY(); eglDestroySurface(display, surface->surface); if(surface->asso_mbe) surface->asso_mbe->tgt = NULL; if(surface->asso_img) _free_vgimage(surface->asso_img); free(surface); } void mbe_copy_source(mbe_t *src_canvas, mbe_t *dst_canvas) { VGImage vg_img; EGLDisplay display; ASSERT(src_canvas->tgt->asso_img != NULL); _MK_CURRENT_CTX(dst_canvas); vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); vgLoadIdentity(); vg_img = SURFACE_VG_IMG(src_canvas); vgDrawImage(vg_img); display = _VG_DISPLAY(); eglSwapBuffers(display, VG_MBE_EGLSURFACE(dst_canvas)); } void mbe_flush(mbe_t *canvas) { EGLDisplay display; EGLSurface *egl_surface; _MK_CURRENT_CTX(canvas); display = _VG_DISPLAY(); egl_surface = VG_MBE_EGLSURFACE(canvas); eglSwapBuffers(display, egl_surface); } mbe_t * mbe_create(mbe_surface_t *surface) { EGLDisplay display; EGLConfig config; EGLContext ctx, shared; VGPath path; EGLint attrib_list[2] = {EGL_NONE}; static VGfloat clear_color[4] = {0, 0, 0, 1}; mbe_t *canvas; int r; display = _VG_DISPLAY(); r = _openvg_find_config(surface->fmt, surface->w, surface->h, &config); if(r != 0) return NULL; /* shared = EGL_NO_CONTEXT; */ shared = init_ctx; ctx = eglCreateContext(display, config, shared, attrib_list); if(ctx == EGL_NO_CONTEXT) return NULL; path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL); if(path == VG_INVALID_HANDLE) { eglDestroyContext(display, ctx); return NULL; } canvas = O_ALLOC(mbe_t); if(canvas == NULL) { eglDestroyContext(display, ctx); vgDestroyPath(path); return NULL; } canvas->src = NULL; canvas->paint = VG_INVALID_HANDLE; canvas->paint_installed = 0; canvas->tgt = surface; canvas->ctx = ctx; canvas->path = path; surface->asso_mbe = canvas; /* Set clear color for the context */ _MK_CURRENT_CTX(canvas); vgSetfv(VG_CLEAR_COLOR, 4, clear_color); return canvas; } void mbe_destroy(mbe_t *canvas) { EGLDisplay display; display = _VG_DISPLAY(); vgDestroyPath(canvas->path); eglDestroyContext(display, canvas->ctx); canvas->tgt->asso_mbe = NULL; /* remove association */ free(canvas); } void mbe_paint_with_alpha(mbe_t *canvas, co_comp_t alpha) { VGfloat color_trans[8] = {1, 1, 1, alpha, 0, 0, 0, 0}; EGLDisplay display; EGLSurface *egl_surface; EGLint w, h; EGLBoolean r; _MK_CURRENT_CTX(canvas); display = _VG_DISPLAY(); egl_surface = VG_MBE_EGLSURFACE(canvas); r = eglQuerySurface(display, egl_surface, EGL_WIDTH, &w); ASSERT(r == EGL_TRUE); r = eglQuerySurface(display, egl_surface, EGL_HEIGHT, &h); ASSERT(r == EGL_TRUE); /* Setup color transform for alpha */ #ifdef OPENVG_1_1 vgSetfv(VG_COLOR_TRANSFORM_VALUES, 8, color_trans); vgSeti(VG_COLOR_TRANSFORM, VG_TRUE); #endif mbe_paint(canvas); #ifdef OPENVG_1_1 vgSeti(VG_COLOR_TRANSFORM, VG_FALSE); #endif } void mbe_paint(mbe_t *canvas) { EGLDisplay display; EGLSurface *egl_surface; EGLint w, h; EGLBoolean r; VGPath path; _MK_CURRENT_CTX(canvas); _MK_CURRENT_PAINT(canvas); if(canvas->src) _mbe_load_pattern_mtx(canvas->src->mtx, NULL, VG_MATRIX_FILL_PAINT_TO_USER); display = _VG_DISPLAY(); egl_surface = VG_MBE_EGLSURFACE(canvas); r = eglQuerySurface(display, egl_surface, EGL_WIDTH, &w); ASSERT(r == EGL_TRUE); r = eglQuerySurface(display, egl_surface, EGL_HEIGHT, &h); ASSERT(r == EGL_TRUE); /* * Disable scissoring and identity transform matrix. * * Transform matrix from path to surface is assigned by * mbe_transform(). Here, we temporary set it to identity, and * restore it after paint. */ vgSeti(VG_SCISSORING, VG_FALSE); vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); vgLoadIdentity(); path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL); vguRect(path, 0, 0, w, h); vgDrawPath(path, VG_FILL_PATH); vgDestroyPath(path); /* re-enable scissoring and restore transform matrix */ vgLoadMatrix(canvas->mtx); vgSeti(VG_SCISSORING, VG_TRUE); } void mbe_clear(mbe_t *canvas) { EGLDisplay display; EGLSurface *egl_surface; EGLint w, h; EGLBoolean r; _MK_CURRENT_CTX(canvas); display = _VG_DISPLAY(); egl_surface = VG_MBE_EGLSURFACE(canvas); r = eglQuerySurface(display, egl_surface, EGL_WIDTH, &w); ASSERT(r == EGL_TRUE); r = eglQuerySurface(display, egl_surface, EGL_HEIGHT, &h); ASSERT(r == EGL_TRUE); /* Clear regions to the color specified by mbe_create() */ vgClear(0, 0, w, h); } void mbe_init() { static EGLSurface init_surf; EGLDisplay display; EGLConfig config; EGLint nconfigs; EGLint attrib_list[] = { EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, EGL_NONE}; EGLint surf_attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE}; EGLBoolean r; display = _VG_DISPLAY(); eglInitialize(display, NULL, NULL); r = eglChooseConfig(display, attrib_list, &config, 1, &nconfigs); ASSERT(r); eglBindAPI(EGL_OPENVG_API); init_ctx = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL); ASSERT(init_ctx != EGL_NO_CONTEXT); init_surf = eglCreatePbufferSurface(display, config, surf_attribs); ASSERT(init_surf != EGL_NO_SURFACE); eglMakeCurrent(display, init_surf, init_surf, init_ctx); }