changeset 618:35a67a837a53 openvg

Use reference count to trace life of _ge_openvg_img_t objects
author Thinker K.F. Li <thinker@branda.to>
date Thu, 08 Jul 2010 13:51:47 +0800
parents 89fee368e367
children 7020ed3c3e37
files include/mb_graph_engine_openvg.h src/graph_engine_openvg.c
diffstat 2 files changed, 119 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/include/mb_graph_engine_openvg.h	Thu Jul 08 11:56:30 2010 +0800
+++ b/include/mb_graph_engine_openvg.h	Thu Jul 08 13:51:47 2010 +0800
@@ -23,7 +23,6 @@
 #define mbe_scaled_font_create(face, fnt_mtx, ctm) ((mbe_scaled_font_t *)NULL)
 #define mbe_font_face_destroy(face)
 #define mbe_set_scaled_font(canvas, scaled)
-#define mbe_pattern_destroy(pattern)
 #define mbe_get_scaled_font(canvas) ((mbe_scaled_font_t *)NULL)
 #define mbe_query_font_face(family, slant, weight) ((mbe_font_face_t *)NULL)
 #define mbe_free_font_face(face)
@@ -120,6 +119,7 @@
  * \note This is type is for internal using of OpenVG graphic engine.
  */
 struct _ge_openvg_img {
+    int ref;
     VGImage img;
     mbe_pattern_t *asso_pattern;
     mbe_surface_t *asso_surface;
@@ -153,6 +153,7 @@
 						grad_stop_t *stops,
 						int stop_cnt);
 extern mbe_pattern_t *mbe_pattern_create_image(mb_img_data_t *img);
+extern void mbe_pattern_destroy(mbe_pattern_t *ptn);
 extern void mbe_pattern_set_matrix(mbe_pattern_t *ptn, co_aix *mtx);
 extern void mbe_set_source_rgba(mbe_t *canvas, co_comp_t r, co_comp_t g,
 				co_comp_t b, co_comp_t a);
@@ -203,22 +204,7 @@
 
 extern mbe_surface_t *mbe_image_surface_create(mb_img_fmt_t fmt,
 					       int w, int h);
-
-static 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)
-	surface->asso_img->asso_surface = NULL;
-    
-    free(surface);
-}
+extern void mbe_surface_destroy(mbe_surface_t *surface);
 
 extern mbe_t *mbe_create(mbe_surface_t *surface);
 extern void mbe_destroy(mbe_t *canvas);
--- a/src/graph_engine_openvg.c	Thu Jul 08 11:56:30 2010 +0800
+++ b/src/graph_engine_openvg.c	Thu Jul 08 13:51:47 2010 +0800
@@ -26,6 +26,75 @@
 	(mtx)[8] = 1;				\
     } while(0)
 
+/*! \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->asso_pattern = NULL;
+    ge_img->asso_surface = 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)
+	return;
+    vgDestroyImage(ge_img->img);
+    free(ge_img);
+}
+
 /*
  * This implementation supports only from image surface.
  */
@@ -47,6 +116,7 @@
     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;
@@ -166,34 +236,25 @@
     if(img->fmt != MB_IFMT_ARGB32)
 	return NULL;
     
-    /* Create and copy pixels into VGImage */
-    vg_img = vgCreateImage(fmt, img->w, img->h,
-			   VG_IMAGE_QUALITY_NONANTIALIASED);
-    if(vg_img == VG_INVALID_HANDLE)
-	return NULL;
-    vgImageSubData(vg_img, img->content, img->stride, fmt,
-		   0, 0, img->w, img->h);
-
     /* Allocate objects */
-    ge_img = O_ALLOC(_ge_openvg_img_t);
+    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;
-	
-
-    /* Initialize objects */
-    ge_img->img = vg_img;
-    ge_img->asso_pattern = NULL;
-    ge_img->asso_surface = NULL;
-
+    
+    /* 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(ge_img);
+    if(ge_img) _free_vgimage(ge_img);
     if(pattern) free(pattern);
     if(paint != VG_INVALID_HANDLE) vgDestroyPaint(paint);
     vgDestroyImage(vg_img);
@@ -201,6 +262,12 @@
 }
 
 void
+mbe_pattern_destroy(mbe_pattern_t *ptn) {
+    if(ptn->asso_img) {
+    }
+}
+
+void
 mbe_pattern_set_matrix(mbe_pattern_t *ptn, co_aix *mtx) {
     co_aix rev[6];
 
@@ -443,6 +510,7 @@
     EGLDisplay display;
     EGLConfig config;
     EGLint attrib_list[5];
+    _ge_openvg_img_t *ge_img;
     mbe_surface_t *mbe_surface;
     int r;
 
@@ -450,7 +518,11 @@
     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();
     attrib_list[0] = EGL_WIDTH;
     attrib_list[1] = w;
@@ -460,23 +532,47 @@
     /* Some implementation does not support pbuffer.
      * We need use some other surface to replace this one.
      */
-    surface = eglCreatePbufferSurface(display, config, attrib_list);
-    if(surface == EGL_NO_SURFACE)
+    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;
 
     return mbe_surface;
 }
 
+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) {
+	surface->asso_img->asso_surface = NULL;
+	_free_vgimage(surface->asso_img);
+    }
+    
+    free(surface);
+}
+
 mbe_t *
 mbe_create(mbe_surface_t *surface) {
     EGLDisplay display;