Mercurial > MadButterfly
view src/graph_engine_openvg.c @ 610:e78bff7d23d3 openvg
create pattern from surface for OpenVG
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Mon, 05 Jul 2010 14:29:26 +0800 |
parents | 6c74bc371e37 |
children | b1d1b6c5af90 |
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 #define MB_2_VG_COLOR(r, g, b, a) ((((int)(0xf * r) & 0xf) << 24) | \ (((int)(0xf * g) & 0xf) << 16) | \ (((int)(0xf * b) & 0xf) << 16) | \ ((int)(0xf * a) & 0xf)) /* * 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; 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; pattern->paint = paint; return pattern; } 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(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; } 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) { vgPaintDestroy(paint); return NULL; } pattern->paint = paint; pattern->asso_img = NULL; 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; /* 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); 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; pattern->paint = paint; pattern->asso_img = ge_img; return pattern; err: if(ge_img) free(ge_img); if(pattern) free(pattern); if(paint != VG_INVALID_HANDLE) vgDestroyPaint(paint); vgDestroyImage(vg_img); return NULL; } 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; if(paint != VG_INVALID_HANDLE && canvas->src == NULL) paint = canvas->paint; /* previous one is also a color paint */ else { paint = vgCreatePaint(); ASSERT(paint != VG_INVALID_HANDLE); canvas->paint = paint; canvas->src = NULL; } color = MB_2_VG_COLOR(r, g, b, a); vgSetColor(paint, color); 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; } 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[16]; 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_NONE; display = _VG_DISPLAY(); r = eglChooseConfig(display, attrib_list, configs, 1, &nconfigs); if(!r) return -1; *config = configs[0]; return 0; } #ifdef EGL_GLX #include <X11/Xlib.h> #include <X11/Xutil.h> static int _get_img_fmt_from_xvisual(Display *display, Visual *visual) { VisualID visual_id; XVisualInfo temp; XVisualInfo *infos; int n; int fmt = -1; visual_id = XVisualIDFromVisual(visual); temp.visualid = visual_id; infos = XGetVisualInfo(display, VisualIDMask, &temp, &n); if(n != 1) return -1; switch(infos->depth) { case 32: fmt = MB_IFMT_ARGB32; break; case 24: fmt = MB_IFMT_RGB24; break; case 16: fmt = MB_IFMT_RGB16_565; break; case 8: fmt = MB_IFMT_A8; break; case 1: fmt = MB_IFMT_A1; break; } return fmt; } /*! \brief Create an EGL window surface for X11. * * This function is compiled only for GLX enabled. */ mbe_surface_t * mbe_vg_win_surface_create(Display *display, Drawable drawable, Visual *visual, int width, int height) { EGLDisplay egl_disp; EGLSurface egl_surface; mbe_surface_t *surface; EGLConfig config; EGLint attrib_list[2] = {EGL_NONE}; int fmt; int r; fmt = _get_img_fmt_from_xvisual(display, visual); if(fmt == -1) return NULL; r = _openvg_find_config(fmt, width, height, &config); if(r != 0) return NULL; egl_disp = eglGetDisplay(display); if(egl_disp == EGL_NO_DISPLAY || egl_disp != _VG_DISPLAY()) return NULL; egl_surface = eglCreateWindowSurface(egl_disp, config, drawable, attrib_list); surface = O_ALLOC(mbe_surface_t); if(surface == NULL) { eglDestroySurface(egl_disp, egl_surface); return NULL; } surface->surface = egl_surface; 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[5]; mbe_surface_t *mbe_surface; int r; r = _openvg_find_config(fmt, w, h, &config); if(r != 0) return NULL; display = _VG_DISPLAY(); attrib_list[0] = EGL_WIDTH; attrib_list[1] = w; attrib_list[2] = EGL_HEIGHT; attrib_list[3] = h; attrib_list[4] = EGL_NONE; /* 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) return NULL; mbe_surface = O_ALLOC(mbe_surface_t); if(mbe_surface == NULL) { eglDestroySurface(display, surface); return NULL; } mbe_surface->surface = surface; mbe_surface->asso_mbe = NULL; mbe_surface->w = w; mbe_surface->h = h; return mbe_surface; } mbe_t * mbe_create(mbe_surface_t *surface) { EGLDisplay display; EGLConfig config; EGLContext ctx, shared; VGPath path; EGLint attrib_list[2] = {EGL_NONE}; mbe_t *canvas; display = _VG_DISPLAY(); 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; 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); } /* * This implementation support only paint with image paint. OpenVG * does not support paint path with an alpha value. But, it supports * to draw image with an alpha value. */ void mbe_paint_with_alpha(mbe_t *canvas, co_comp_t alpha) { VGImage vg_img; _ge_openvg_img_t *ge_img; _MK_CURRENT_CTX(canvas); ASSERT(canvas->src != NULL && canvas->src->asso_img != NULL); ge_img = canvas->src->asso_img; vg_img = ge_img->img; vgDrawImage(vg_img); } void mbe_paint(mbe_t *canvas) { EGLDisplay display; EGLint w, h; EGLBoolean r; VGPath path; _MK_CURRENT_CTX(canvas); _MK_CURRENT_PAINT(canvas); display = _VG_DISPLAY(); r = eglQuerySurface(display, canvas->tgt, EGL_WIDTH, &w); ASSERT(r == EGL_TRUE); r = eglQuerySurface(display, canvas->tgt, EGL_HEIGHT, &h); ASSERT(r == EGL_TRUE); vgSeti(VG_SCISSORING, VG_FALSE); 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); vgSeti(VG_SCISSORING, VG_TRUE); } void mbe_clear(mbe_t *canvas) { VGPaint paint; _MK_CURRENT_CTX(canvas); paint = vgCreatePaint(); ASSERT(paint != VG_INVALID_HANDLE); vgSetColor(paint, 0); vgSetPaint(paint, VG_FILL_PATH); vgSeti(VG_BLEND_MODE, VG_BLEND_SRC); vgDrawPath(canvas->path, VG_FILL_PATH); vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER); vgDestroyPaint(paint); canvas->paint_installed = 0; }