changeset 619:7020ed3c3e37 openvg

Actiavte a VGImage before using a pattern paint or image surface. - A VGImage can only activated for a pattern or an image in any instance. - _ge_openvg_img trace the object activated for currently and its deactivation function. - everytime a pattern paint or image surface will be used, the current activated one will be deactivated, and activate a new one.
author Thinker K.F. Li <thinker@branda.to>
date Thu, 08 Jul 2010 18:44:26 +0800
parents 35a67a837a53
children 3f544e876939
files include/mb_graph_engine_openvg.h src/graph_engine_openvg.c
diffstat 2 files changed, 111 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/include/mb_graph_engine_openvg.h	Thu Jul 08 13:51:47 2010 +0800
+++ b/include/mb_graph_engine_openvg.h	Thu Jul 08 18:44:26 2010 +0800
@@ -110,10 +110,16 @@
  * used to make sure previous associated pattern or surface being
  * released before new association.
  *
- * Functions must release assocation specified by
- * _ge_openvg_img::asso_pattern or _ge_openvg_img::asso_surface before
- * new association, and record new association as one of thes two
- * vairables.
+ * 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.
@@ -121,8 +127,8 @@
 struct _ge_openvg_img {
     int ref;
     VGImage img;
-    mbe_pattern_t *asso_pattern;
-    mbe_surface_t *asso_surface;
+    void *activated_for;
+    void (*deactivate_func)(void *obj);
 };
 
 #define MB_MATRIX_2_OPENVG(vgmtx, mtx) do {	\
@@ -140,6 +146,8 @@
 extern EGLNativeDisplayType _ge_openvg_disp_id;
 extern mbe_t *_ge_openvg_current_canvas;
 extern void _mbe_load_pattern_mtx(VGfloat *mtx1, VGfloat *mtx2, int mode);
+extern void _ge_vg_img_activate_for_pattern(mbe_pattern_t *ptn);
+extern void _ge_vg_img_activate_for_surface(mbe_surface_t *surf);
 
 extern mbe_pattern_t *mbe_pattern_create_for_surface(mbe_surface_t *surface);
 extern mbe_pattern_t *mbe_pattern_create_radial(co_aix cx0, co_aix cy0,
@@ -175,12 +183,20 @@
 			   (canvas)->tgt->surface,		\
 			   (canvas)->ctx);			\
 	}							\
+	/* \sa _ge_openvg_img_t */				\
+	_ge_vg_img_activate_for_surface((canvas)->tgt);		\
     } while(0)
 /* TODO: switch VGImage between VGPaint and surface. */
 #define _MK_CURRENT_PAINT(canvas)					\
-    if((canvas)->paint_installed) {					\
-	vgSetPaint((canvas)->paint, VG_FILL_PATH|VG_STROKE_PATH);	\
-    }
+    do {								\
+	if((canvas)->paint_installed == 0) {				\
+	    vgSetPaint((canvas)->paint, VG_FILL_PATH|VG_STROKE_PATH);	\
+	    (canvas)->paint_installed = 1;				\
+	}								\
+	/* \sa _ge_openvg_img_t */					\
+	if((canvas)->src)						\
+	    _ge_vg_img_activate_for_pattern((canvas)->src);		\
+    } while(0)
 
 #define mbe_transform(canvas, _mtx)				\
     do {							\
--- a/src/graph_engine_openvg.c	Thu Jul 08 13:51:47 2010 +0800
+++ b/src/graph_engine_openvg.c	Thu Jul 08 18:44:26 2010 +0800
@@ -80,8 +80,8 @@
     }
     ge_img->ref = 1;
     ge_img->img = vg_img;
-    ge_img->asso_pattern = NULL;
-    ge_img->asso_surface = NULL;
+    ge_img->activated_for = NULL;
+    ge_img->deactivate_func = NULL;
 
     return ge_img;
 }
@@ -89,12 +89,89 @@
 /*! \brief Free image object for OpenVG */
 static void
 _free_vgimage(_ge_openvg_img_t *ge_img) {
-    if(--ge_img->ref > 0)
+    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) {
+}
+
+/*! \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.
  */
@@ -263,8 +340,10 @@
 
 void
 mbe_pattern_destroy(mbe_pattern_t *ptn) {
-    if(ptn->asso_img) {
-    }
+    if(ptn->asso_img)
+	_free_vgimage(ptn->asso_img);
+    vgDestroyPaint(ptn->paint);
+    free(ptn);
 }
 
 void
@@ -498,6 +577,7 @@
     }
 
     surface->surface = egl_surface;
+    surface->asso_img = NULL;
 
     return surface;
 }
@@ -565,10 +645,8 @@
     if(surface->asso_mbe)
 	surface->asso_mbe->tgt = NULL;
 
-    if(surface->asso_img) {
-	surface->asso_img->asso_surface = NULL;
+    if(surface->asso_img)
 	_free_vgimage(surface->asso_img);
-    }
     
     free(surface);
 }