2 Copyright 2004-2005 Chris Tallon, 2006,2011-2012 Marten Richter
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP. If not, see <https://www.gnu.org/licenses/>.
20 #include <stdio.h> // really?
22 #include <sys/syscall.h>
23 #include <fontconfig/fontconfig.h>
30 #include "messagequeue.h"
31 #include "teletxt/txtfont.h"
33 #include "osdopenvg.h"
35 #define EXTERNALPICTURE(name, fname, fileextension) extern uint8_t name ## _data[] asm("_binary_other_"#fname"_"#fileextension"_start"); \
36 extern uint8_t name ## _data_end[] asm("_binary_other_"#fname"_"#fileextension"_end");
40 #undef EXTERNALPICTURE
42 #define BACKBUFFER_WIDTH 1280
43 #define BACKBUFFER_HEIGHT 720
45 OsdOpenVG::OsdOpenVG()
49 lastrendertime = getTimeMS();
51 const char* fontname = "Droid Sans:style=Regular";
52 cur_fontname = static_cast<char*>(malloc(strlen(fontname) + 1));
53 strcpy(cur_fontname, fontname);
55 #define EXTERNALPICTURE(name, fname, fileextension) static_artwork_begin[sa_ ## name]=name ## _data;
59 #undef EXTERNALPICTURE
60 #define EXTERNALPICTURE(name, fname, fileextension) static_artwork_end[sa_ ## name]=name ## _data_end;
64 #undef EXTERNALPICTURE
67 OsdOpenVG::~OsdOpenVG()
69 if (initted) shutdown();
71 if (cur_fontname) free(cur_fontname);
73 if (freetype_inited) FT_Done_Face(ft_face);
75 // I think the following is broken as it is, but also possibly it shouldn't be free()ing the memory
76 // pointed at anyway, so it's correctly not working?!
78 if (!fontnames.size())
80 std::vector<char*>::iterator itty = fontnames.begin();
82 while (itty != fontnames.end())
92 if (fontnames_keys.size())
94 std::vector<char*>::iterator itty = fontnames_keys.begin();
96 while (itty != fontnames_keys.end())
107 int OsdOpenVG::init()
109 if (initted) return 0;
113 //First get connection to egl
114 egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
115 if (egl_display == EGL_NO_DISPLAY)
117 Log::getInstance()->log("OSD", Log::WARN, "Could not get egl display! %x", eglGetError());
122 if (eglInitialize(egl_display, NULL, NULL) == EGL_FALSE)
124 Log::getInstance()->log("OSD", Log::WARN, "Initialising display failed! %x", eglGetError());
129 const char* query_str = eglQueryString(egl_display, EGL_CLIENT_APIS);
131 if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
132 else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x", eglGetError());
134 query_str = eglQueryString(egl_display, EGL_EXTENSIONS);
136 if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
137 else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x", eglGetError());
139 if (eglBindAPI(EGL_OPENVG_API) == EGL_FALSE)
141 Log::getInstance()->log("OSD", Log::WARN, "Binding openvg api failed! %x", eglGetError());
146 const EGLint attributs[] =
148 EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,
149 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
150 EGL_CONFORMANT, EGL_OPENVG_BIT,
152 }; // Here, we might have to select the resolution!
156 if (eglChooseConfig(egl_display, attributs, &egl_ourconfig, 1, &number) == EGL_FALSE)
158 Log::getInstance()->log("OSD", Log::WARN, "Choosing egl config failed! %x", eglGetError());
163 egl_context = eglCreateContext(egl_display, egl_ourconfig, NULL, NULL);
165 if (egl_context == EGL_NO_CONTEXT)
167 Log::getInstance()->log("OSD", Log::WARN, "Creating egl context failed! %x", eglGetError());
172 // warning broadcom specific, get display size!
173 display_width = display_height = 0;
175 if (graphics_get_display_size(0, &display_width, &display_height) < 0)
177 Log::getInstance()->log("OSD", Log::WARN, "Getting display size failed! (BCM API) ");
182 Log::getInstance()->log("OSD", Log::NOTICE, "Displaysize is %d x %d ", display_width, display_height);
183 VC_RECT_T dst_rect = {0, 0, (int32_t)display_width, (int32_t)display_height};
184 VC_RECT_T src_rect = {0, 0, BACKBUFFER_WIDTH << 16, BACKBUFFER_HEIGHT << 16};
185 VC_RECT_T src_rect_bg = {0, 0, 16 << 16, 16 << 16};
186 // VC_RECT_T src_rect_im={0,0,16,16};
188 uint32_t back_image_ptr;
189 bcm_backres = vc_dispmanx_resource_create(VC_IMAGE_RGBX32, 16, 16, &back_image_ptr);
191 updateBackgroundColor(DrawStyle::WALLPAPER);
193 DISPMANX_UPDATE_HANDLE_T bcm_update;
194 bcm_display = vc_dispmanx_display_open(0);
195 bcm_update = vc_dispmanx_update_start(0);
196 bcm_element = vc_dispmanx_element_add(bcm_update, bcm_display,
198 &src_rect, DISPMANX_PROTECTION_NONE, 0, 0, (DISPMANX_TRANSFORM_T) 0);
201 bcm_background = vc_dispmanx_element_add(bcm_update, bcm_display,
202 0, &dst_rect, bcm_backres,
203 &src_rect_bg, DISPMANX_PROTECTION_NONE, 0, 0, (DISPMANX_TRANSFORM_T) 0);
205 vc_dispmanx_update_submit_sync(bcm_update);
207 static EGL_DISPMANX_WINDOW_T nativewindow;
208 nativewindow.element = bcm_element;
209 nativewindow.height = BACKBUFFER_HEIGHT;
210 nativewindow.width = BACKBUFFER_WIDTH;
212 egl_surface = eglCreateWindowSurface(egl_display, egl_ourconfig, &nativewindow, NULL);
213 if (egl_surface == EGL_NO_SURFACE)
215 Log::getInstance()->log("OSD", Log::WARN, "Creating egl window surface failed!");
220 Log::getInstance()->log("OSD", Log::DEBUG, "Making egl current in1%d", syscall(SYS_gettid));
222 if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context) == EGL_FALSE)
224 Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed");
231 query_str = reinterpret_cast<const char*>(vgGetString(VG_VERSION));
233 if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
234 else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x", vgGetError());
236 query_str = reinterpret_cast<const char*>(vgGetString(VG_VENDOR));
238 if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
239 else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x", vgGetError());
241 query_str = reinterpret_cast<const char*>(vgGetString(VG_RENDERER));
243 if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
244 else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x", vgGetError());
246 query_str = reinterpret_cast<const char*>(vgGetString(VG_EXTENSIONS));
248 if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
249 else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x", vgGetError());
251 aspect_correction = ((float)BACKBUFFER_HEIGHT) / 576.f / (((float)BACKBUFFER_WIDTH) / 720.f);
254 if (!fontnames.size())
256 //inspired by and copied from vdr's code
258 FcObjectSet* objset = FcObjectSetBuild(FC_FAMILY, FC_STYLE, NULL);
259 FcPattern* pattern = FcPatternCreate();
260 FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
261 FcFontSet* fonts = FcFontList(NULL, pattern, objset);
263 for (int i = 0; i < fonts->nfont; i++)
265 char* s = (char*)FcNameUnparse(fonts->fonts[i]);
269 char* c = strchr(s, ':');
273 char* s2 = strchr(c + 1, ',');
278 char* p = strchr(s, ',');
283 else memmove(p, c, strlen(c) + 1);
286 char* key = (char*)malloc(strlen(s) + 1);
288 fontnames_keys.push_back(key);
289 char* s2 = strstr(s, "style=");
293 memmove(s2, s2 + 6, strlen(s2 + 6) + 1);
296 fontnames.push_back(s);
300 FcFontSetDestroy(fonts);
301 FcPatternDestroy(pattern);
302 FcObjectSetDestroy(objset);
305 if (!loadFont(false))
310 vgttfont = vgCreateFont(0);
311 vgttpaint = vgCreatePaint();
312 vgSetParameteri( vgttpaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
313 vgSetColor(vgttpaint, 0xffffffff);
315 eglSwapInterval(egl_display, 1);
317 Log::getInstance()->log("OSD", Log::DEBUG, "Making egl current out 1%d", syscall(SYS_gettid));
318 eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
319 //Now we will create the Screen
320 initted = true; // must set this here or create surface won't work
322 /*if (((VideoOMX*)Video::getInstance())->initUsingOSDObjects()!=1) { //call Video for init stuff
330 #ifdef PICTURE_DECODER_OMX
331 imageomx = new ImageOMX(&reader);
332 reader.addDecoder(imageomx);
338 void OsdOpenVG::updateBackgroundColor(DrawStyle bg)
340 unsigned int color[16 * 16];
342 if (!bcm_backres) return;
344 VC_RECT_T src_rect_im = {0, 0, 16, 16};
346 if (bg.ft != DrawStyle::GradientLinear)
351 //memset(color,0xFF,sizeof(unsigned int)*4*8);
352 for (int j = 0; j < 16; j++)
354 int helpr = (((15 - j) * bg.red) + (j * bg.grad_col[0].red)) / 15;
355 int helpb = (((15 - j) * bg.blue) + (j * bg.grad_col[0].blue)) / 15;
356 int helpg = (((15 - j) * bg.green) + (j * bg.grad_col[0].green)) / 15;
357 //unsigned int cur_col=help | (help<< 8) | (help<< 16) | (0xFF<< 24);
358 unsigned int cur_col = helpr | (helpg << (8)) | (helpb << (16)) | (0xFF << (24));
360 for (int i = 0; i < 16; i++)
362 color[i + 16 * j] = cur_col;
366 vc_dispmanx_resource_write_data(bcm_backres, VC_IMAGE_RGBX32, 16 * 4, color, &src_rect_im);
369 void OsdOpenVG::getScreenSize(int& width, int& height)
371 width = BACKBUFFER_WIDTH;
372 height = BACKBUFFER_HEIGHT;
375 void OsdOpenVG::getRealScreenSize(int& width, int& height)
377 width = display_width;
378 height = display_height;
381 bool OsdOpenVG::screenShot(void* buffer, int width, int height, bool osd /*include osd*/)
383 if (!initted) return false;
385 if (!buffer) return false;
387 DISPMANX_RESOURCE_HANDLE_T res;
388 DISPMANX_DISPLAY_HANDLE_T display;
392 res = vc_dispmanx_resource_create(VC_IMAGE_RGBA32, width, height, &image_ptr);
393 display = vc_dispmanx_display_open(0);
397 vc_dispmanx_snapshot(display, res,
398 static_cast<DISPMANX_TRANSFORM_T>(DISPMANX_SNAPSHOT_NO_RGB | DISPMANX_SNAPSHOT_FILL/*|DISPMANX_SNAPSHOT_PACK*/));
402 vc_dispmanx_snapshot(display, res,
403 static_cast<DISPMANX_TRANSFORM_T>(DISPMANX_SNAPSHOT_FILL));
406 vc_dispmanx_rect_set(&rect, 0, 0, width, height);
407 vc_dispmanx_resource_read_data(res, &rect, buffer, width * 4);
408 vc_dispmanx_resource_delete(res);
409 vc_dispmanx_display_close(display);
413 void OsdOpenVG::initPaths()
416 current = vgCreatePath(VG_PATH_FORMAT_STANDARD,
417 VG_PATH_DATATYPE_F, 1.f, 0.f,
418 0, 0, VG_PATH_CAPABILITY_ALL);
420 vguLine(current, 0.f, 0.f, 1.f, 0.f);
422 std_paths[PIHorzLine] = current;
424 current = vgCreatePath(VG_PATH_FORMAT_STANDARD,
425 VG_PATH_DATATYPE_F, 1.f, 0.f,
426 0, 0, VG_PATH_CAPABILITY_ALL);
427 vguLine(current, 0.f, 0.f, 0.f, 1.f);
429 std_paths[PIVertLine] = current;
431 current = vgCreatePath(VG_PATH_FORMAT_STANDARD,
432 VG_PATH_DATATYPE_F, 1.f, 0.f,
433 0, 0, VG_PATH_CAPABILITY_ALL);
434 //vguRect(current,0.f,0.f,1.f,1.f);
435 vguRect(current, 0.f, 0.f, 1.f, 1.f);
437 std_paths[PIRectangle] = current;
439 current = vgCreatePath(VG_PATH_FORMAT_STANDARD,
440 VG_PATH_DATATYPE_F, 1.f, 0.f,
442 vguEllipse(current, 0.f, 0.f, 1.f, 1.f);
444 std_paths[PIPoint] = current;
447 void OsdOpenVG::destroyPaths()
449 vgDestroyPath(std_paths[PIHorzLine]);
450 vgDestroyPath(std_paths[PIVertLine]);
451 vgDestroyPath(std_paths[PIRectangle]);
452 vgDestroyPath(std_paths[PIPoint]);
455 int OsdOpenVG::stopUpdate()
463 void OsdOpenVG::purgeAllReferences()
466 drawstyleHandlesRefCounts.clear(); // remove all references
469 map<void *,ImageIndex>::iterator mitty=monobitmaps.begin();
470 while (mitty!=monobitmaps.end()) {
471 vgDestroyImage((VGImage)(*mitty).second);
476 / *map<string,ImageIndex>::iterator jitty=jpegs.begin();
477 while (jitty!=jpegs.end()) {
478 vgDestroyImage((VGImage)(*jitty).second);
483 map<TVMediaInfo,ImageIndex>::iterator titty=tvmedias.begin();
484 while (titty!=tvmedias.end()) {
485 vgDestroyImage((VGImage)(*titty).second);
490 map<pair<Colour*,unsigned int>,unsigned int>::iterator sitty=drawstyleHandles.begin();
491 while (sitty!=drawstyleHandles.end()) {
492 vgDestroyPaint((VGPaint)(*sitty).second);
495 drawstyleHandles.clear();
499 int OsdOpenVG::shutdown()
503 #ifdef PICTURE_DECODER_OMX
504 if (imageomx) reader.removeDecoder(imageomx);
508 if (!initted) return 0;
511 Log::getInstance()->log("OSD", Log::DEBUG, "shutdown mark1");
513 Log::getInstance()->log("OSD", Log::DEBUG, "shutdown mark1a");
515 //(((VideoOMX*)Video::getInstance())->shutdownUsingOSDObjects());
516 if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context) == EGL_FALSE)
518 Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed in shutdown %x", eglGetError());
521 if (eglBindAPI(EGL_OPENVG_API) == EGL_FALSE)
523 Log::getInstance()->log("OSD", Log::WARN, "Binding openvg api thread failed! %x", eglGetError());
526 Log::getInstance()->log("OSD", Log::DEBUG, "shutdown mark2");
528 Log::getInstance()->log("OSD", Log::DEBUG, "shutdown mark3");
533 //purgeAllReferences();
535 vgDestroyFont(vgfont);
536 vgDestroyFont(vgttfont);
537 vgDestroyPaint(vgttpaint);
539 float colclear[] = {0.8f, 0.8f, 0.8f, 1.f};
540 vgSetfv(VG_CLEAR_COLOR, 4, colclear);
541 vgClear(0, 0, BACKBUFFER_WIDTH, BACKBUFFER_HEIGHT);
542 eglSwapBuffers(egl_display, egl_surface);
543 Log::getInstance()->log("OSD", Log::DEBUG, "Making egl current out final");
544 eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
546 if (eglDestroySurface(egl_display, egl_surface) == EGL_FALSE)
548 Log::getInstance()->log("OSD", Log::ERR, "eglDestroySurface failed %x", eglGetError());
551 if (eglDestroyContext(egl_display, egl_context) == EGL_FALSE)
553 Log::getInstance()->log("OSD", Log::ERR, "eglDestroyContext failed %x", eglGetError());
556 if (eglTerminate(egl_display ) == EGL_FALSE)
558 Log::getInstance()->log("OSD", Log::ERR, "eglTerminate failed %x", eglGetError());
561 DISPMANX_UPDATE_HANDLE_T bcm_update;
562 bcm_update = vc_dispmanx_update_start(0);
564 vc_dispmanx_element_remove(bcm_update, bcm_element);
565 vc_dispmanx_element_remove(bcm_update, bcm_background);
566 vc_dispmanx_update_submit_sync(bcm_update);
567 vc_dispmanx_resource_delete(bcm_backres);
569 vc_dispmanx_display_close(bcm_display);
573 void OsdOpenVG::threadMethod()
575 // We have to claim the egl context for this thread
576 Log::getInstance()->log("OSD", Log::NOTICE, "Entering drawing thread");
578 if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context) == EGL_FALSE)
580 Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed in thread %x", eglGetError());
584 if (eglBindAPI(EGL_OPENVG_API) == EGL_FALSE)
586 Log::getInstance()->log("OSD", Log::WARN, "Binding openvg api thread failed! %x", eglGetError());
598 long long time1 = getTimeMS();
600 if ((time1 - lastrendertime) > 200) //5 fps for OSD updates are enough, avoids tearing
607 lastrendertime = getTimeMS();
613 ts = time1 - lastrendertime;
616 if (processTasks()) ts = 0;
619 if (!threadIsActive())
621 if (eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT ) == EGL_FALSE)
623 Log::getInstance()->log("OSD", Log::WARN, "Making egl Current out thread failed");
631 struct timespec target_time;
632 clock_gettime(CLOCK_REALTIME, &target_time);
633 target_time.tv_nsec += 1000000LL * ts;
635 if (target_time.tv_nsec > 999999999)
637 target_time.tv_nsec -= 1000000000L;
638 target_time.tv_sec += 1;
642 threadWaitForSignalTimed(&target_time);
647 eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
650 void OsdOpenVG::InternalRendering()
653 Colour bg = DrawStyle::WALLPAPER;
654 float colclear[] = {1.f, 1.0f, 1.f, 1.f};
656 if (bg.alpha == 0) colclear[3] = 0.f;
658 vgSetfv(VG_CLEAR_COLOR, 4, colclear);
659 vgClear(0, 0, BACKBUFFER_WIDTH, BACKBUFFER_HEIGHT);
660 vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);
662 drawSurfaces(); //iterate through and draws all commands
664 //Show it to the user!
665 eglSwapBuffers(egl_display, egl_surface);
671 float OsdOpenVG::getFontHeight()
673 return font_height; //dummy
676 float OsdOpenVG::getCharWidth(wchar_t c)
678 if (c < 256) return byte_char_width[c];
680 unsigned int glyph_index = FT_Get_Char_Index(ft_face, c);
681 return font_exp_x[glyph_index];
684 unsigned int OsdOpenVG::loadTTchar(cTeletextChar c)
686 unsigned int glyph_index = c.getGlyphIndex();
688 if (tt_font_chars.find(glyph_index) != tt_font_chars.end())
693 unsigned int buffer[10];
694 const VGfloat glyphOrigin[] = { 0.f, 0.f };
695 const VGfloat escapement[] = { 12.f, 0.f };
696 unsigned int* charmap = GetFontChar(c, buffer);
698 if (!charmap) return 0; //invalid char
700 for (int i = 0; i < 10; i++)
702 buffer[i] = charmap[i] >> 4;
705 VGImage handle = vgCreateImage(
709 VG_IMAGE_QUALITY_NONANTIALIASED | VG_IMAGE_QUALITY_FASTER
710 | VG_IMAGE_QUALITY_BETTER);
711 vgImageSubData(handle, buffer, 4, VG_A_1, 0, 0, 12, 10);
715 handle, const_cast<VGfloat*>(glyphOrigin), const_cast<VGfloat*>(escapement));
716 vgDestroyImage(handle);
717 tt_font_chars[glyph_index] = 1;
722 int OsdOpenVG::getFontNames(const char*** names, const char*** names_keys)
724 *names = const_cast<const char**>(&(fontnames[0]));
725 *names_keys = const_cast<const char**>(&(fontnames_keys[0]));
726 return fontnames.size();
729 void OsdOpenVG::setFont(const char* fontname)
731 if (strcmp(fontname, cur_fontname))
734 if (cur_fontname) free(cur_fontname);
736 cur_fontname = static_cast<char*>(malloc(strlen(fontname) + 1));
737 strcpy(cur_fontname, fontname);
739 struct OpenVGCommand comm;
740 comm.task = OVGreplacefont;
741 putOpenVGCommand(comm, false);
745 int OsdOpenVG::loadFont(bool newfont)
748 float font_size = 16.f;
750 if (!freetype_inited)
752 error = FT_Init_FreeType(&ft_library);
756 Log::getInstance()->log("OSD", Log::WARN, "Could not load freetype %x", error);
761 if (!freetype_inited || newfont)
763 //first get the filename algorith extracted from vdr by Klaus Schmidinger
765 FcPattern* pattern = FcNameParse(reinterpret_cast<FcChar8*>(cur_fontname));
766 FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
767 FcConfigSubstitute(NULL, pattern, FcMatchPattern);
768 FcDefaultSubstitute(pattern);
770 FcFontSet* fonts = FcFontSort(NULL, pattern, FcFalse, NULL, &fres);
771 FcChar8* filename = NULL;
775 for (int i = 0; i < fonts->nfont; i++)
778 FcPatternGetBool(fonts->fonts[i], FC_SCALABLE, 0, &canscale);
782 FcPatternGetString(fonts->fonts[i], FC_FILE, 0, &filename);
787 FcFontSetDestroy(fonts);
791 Log::getInstance()->log("OSD", Log::CRIT, "Could not locate a font! Abort!");
795 FcPatternDestroy(pattern);
797 Log::getInstance()->log("OSD", Log::NOTICE, "Load Font %s: %s", cur_fontname, filename);
798 // second load the font
800 error = FT_New_Face(ft_library, reinterpret_cast<const char*>(filename), 0, &new_ft_face);
804 Log::getInstance()->log("OSD", Log::WARN, "Could not load font face %x %s", error, filename);
808 error = FT_Set_Char_Size(new_ft_face, 0, font_size * 256, 0, 0 /*dpi*/);
812 FT_Done_Face(new_ft_face);
813 Log::getInstance()->log("OSD", Log::WARN, "Could not set face size %x", error);
817 FT_Face old_ft_face = ft_face; // do it thread safe
818 ft_face = new_ft_face;
820 if (freetype_inited) FT_Done_Face(old_ft_face);//
822 freetype_inited = true;
825 vgfont = vgCreateFont(0);
828 font_height = ft_face->size->metrics.height / 256.f;
829 cur_char = FT_Get_First_Char(ft_face, &glyph);
830 std::vector<VGubyte> segments;
831 std::vector<VGfloat> coord;
832 segments.reserve(256);
835 //Log::getInstance()->log("OSD", Log::DEBUG, "Create Glyph test %d %x %x %d",cur_char,font_data_end,font_data,glyph);
838 error = FT_Load_Glyph(ft_face, glyph, FT_LOAD_DEFAULT);
842 cur_char = FT_Get_Next_Char(ft_face, cur_char, &glyph);
843 Log::getInstance()->log("OSD", Log::WARN, "Could not load glyph %x %c", error);
848 FT_Outline ot = ft_face->glyph->outline;
852 if (ot.n_contours == 0)
854 path = VG_INVALID_HANDLE;
858 path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
859 1.0f, 0.f, 0, 0, VG_PATH_CAPABILITY_ALL);
862 FT_Vector* pt = ot.points;
863 const char* tags = ot.tags;
864 const short* cont = ot.contours;
865 short n_cont = ot.n_contours;
867 //short n_point=ot.n_points;
869 for (short point = 0; n_cont != 0; cont++, n_cont--)
871 short next_cont = *cont + 1;
874 short first_point = point;
876 //Log::getInstance()->log("OSD", Log::DEBUG, "runs %d",*cont);
877 for (; point < next_cont; point++)
879 char tag = tags[point];
880 FT_Vector fpoint = pt[point];
882 // Log::getInstance()->log("OSD", Log::DEBUG, "tag %d point %d %d: %d %d",tag,fpoint.x,fpoint.y,point,n_point);
885 segments.push_back(VG_MOVE_TO);
888 else if (tag & 0x1) //on curve
892 segments.push_back(VG_LINE_TO);
894 else if (last_tag & 0x2)
896 segments.push_back(VG_CUBIC_TO);
900 segments.push_back(VG_QUAD_TO);
908 if (!(last_tag & 0x1))
910 segments.push_back(VG_QUAD_TO);
911 int coord_size = coord.size();
912 VGfloat x = (coord[coord_size - 2] + ((float)fpoint.x) / 256.f) * 0.5f * aspect_correction;
913 VGfloat y = (coord[coord_size - 1] + (font_size - ((float)fpoint.y) / 256.f)) * 0.5f;
921 coord.push_back(((float)fpoint.x)*aspect_correction / 256.);
922 coord.push_back(font_size - ((float)fpoint.y) / 256.);
923 //Log::getInstance()->log("OSD", Log::DEBUG, "Create APD Glyph coord %d %d %g %g",fpoint.x,fpoint.y,coord[coord.size()-2],coord[coord.size()-1]);
926 if (!(last_tag & 0x1))
930 segments.push_back(VG_CUBIC_TO);
934 segments.push_back(VG_QUAD_TO);
937 coord.push_back(((float)pt[first_point].x)*aspect_correction / 256.);
938 coord.push_back(font_size - ((float)pt[first_point].y) / 256.);
941 //segments.push_back(VG_CLOSE_PATH);
944 vgAppendPathData(path, segments.size(), &segments[0], &coord[0]);
945 /* for (int m=0;m<segments.size();m++) {
950 Log::getInstance()->log("OSD", Log::DEBUG, "Move To %g %g",coord[n],coord[n+1]);n+=2; break;
952 Log::getInstance()->log("OSD", Log::DEBUG, "Line To %g %g",coord[n],coord[n+1]);n+=2; break;
954 Log::getInstance()->log("OSD", Log::DEBUG, "Cubic To %g %g %g %g %g %g",coord[n],coord[n+1],coord[n+2],coord[n+3],coord[n+4],coord[n+5]);n+=6; break;
956 Log::getInstance()->log("OSD", Log::DEBUG, "Quad To %g %g %g %g",coord[n],coord[n+1],coord[n+2],coord[n+3]);n+=4; break;
958 Log::getInstance()->log("OSD", Log::DEBUG, "Close Path"); break;
962 //vguRect(path,0.f,0.f,1.f,1.f);
963 //Log::getInstance()->log("OSD", Log::DEBUG, "Create APD Glyph %d %x",segments.size(),vgGetError());
966 VGfloat ori[] = {0.f, 0.f};
967 VGfloat esp[] = {ft_face->glyph->advance.x / 256.f * aspect_correction, ft_face->glyph->advance.y / 256.f};
968 font_exp_x[glyph] = ft_face->glyph->advance.x / 256.f * aspect_correction; //recalculate
970 vgSetGlyphToPath(vgfont, glyph, path, VG_FALSE, ori, esp);
972 //Log::getInstance()->log("OSD", Log::DEBUG, "Create Glyph %d %d %x",path,glyph,vgGetError());
973 if (path != VG_INVALID_HANDLE)
978 cur_char = FT_Get_Next_Char(ft_face, cur_char, &glyph);
981 for (int i = 0; i < 256; i++)
983 unsigned int glyph_index = FT_Get_Char_Index(ft_face, i);
984 byte_char_width[i] = font_exp_x[glyph_index];
990 void OsdOpenVG::drawSetTrans(SurfaceInfo& sc)
992 vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
994 vgScale(((float)BACKBUFFER_WIDTH) / 720.f, -((float)BACKBUFFER_HEIGHT) / 576.f);
995 vgTranslate(0.f + sc.x, -576.f + sc.y);
997 vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE);
999 vgScale(((float)BACKBUFFER_WIDTH) / 720.f, -((float)BACKBUFFER_HEIGHT) / 576.f);
1000 vgTranslate(0.f + sc.x, -576.f + sc.y);
1002 vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
1004 vgScale(((float)BACKBUFFER_WIDTH) / 720.f, -((float)BACKBUFFER_HEIGHT) / 576.f);
1005 vgTranslate(0.f + sc.x, -576.f + sc.y);
1006 clip_shift_x = sc.x;
1007 clip_shift_y = sc.y;
1009 //vgTranslate(0.f+sc.x,576.f-sc.y);
1010 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw Translate %g %g",sc.x,sc.y);
1013 void OsdOpenVG::executeDrawCommand(SVGCommand& command)
1015 VGfloat save_matrix[9];
1016 VGfloat save_matrix2[9];
1018 switch (command.instr)
1022 vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
1024 // rgba = vgGetColor((VGPaint) command.handle);
1025 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw Path %d %x %g %g %g %g",command.handle,command.target.path_index,command.x,command.y,command.w,command.h);
1026 //vgSeti(VG_FILL_RULE,);
1028 vgGetMatrix(save_matrix);
1029 vgSetPaint(static_cast<VGPaint>(command.handle), VG_FILL_PATH);
1030 vgSetPaint(static_cast<VGPaint>(command.handle), VG_STROKE_PATH);
1031 vgTranslate(command.x, command.y);
1032 vgScale(command.w, command.h);
1033 vgDrawPath(std_paths[command.target.path_index], VG_FILL_PATH);
1034 vgLoadMatrix(save_matrix);
1039 vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
1040 vgGetMatrix(save_matrix);
1041 VGfloat imagewidth = vgGetParameteri((VGImage) command.target.image, VG_IMAGE_WIDTH);
1042 VGfloat imageheight = vgGetParameteri((VGImage) command.target.image, VG_IMAGE_HEIGHT);
1044 //vgScale(command.w,command.h);
1046 if (command.handle) //special behaviout for bw images they act as a mask on the current paint
1048 vgTranslate(command.x, command.y);
1049 vgSetPaint(static_cast<VGPaint>(command.handle), VG_FILL_PATH);
1050 vgSetPaint(static_cast<VGPaint>(command.handle), VG_STROKE_PATH);
1051 vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_STENCIL);
1052 vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
1053 vgScale(aspect_correction, 1.f);
1054 vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER);
1055 vgGetMatrix(save_matrix2);
1056 vgScale(imagewidth, imageheight);
1060 //vgScale(720.f/((float)BACKBUFFER_WIDTH), 576.f/((float)BACKBUFFER_HEIGHT));
1061 float scalex = command.w / imagewidth;
1062 float scaley = command.h / imageheight;
1063 float tx = command.x;
1064 float ty = command.y;
1066 if (command.corner == TopLeftLimited)
1068 if (scalex != 0.f && scaley != 0.f)
1070 float imageaspect = imagewidth / imageheight;
1071 float boxaspect = command.w / command.h / aspect_correction;
1073 if (imageaspect > boxaspect)
1076 ty += (command.h - imageheight * scalex / aspect_correction) * 0.5f;
1081 tx += (command.w - imagewidth * scaley * aspect_correction) * 0.5f;
1086 if (scalex == 0.f && scaley == 0.f)
1088 scalex = aspect_correction;
1091 else if (scalex == 0.f)
1093 scalex = scaley * aspect_correction;
1095 else if (scaley == 0.f)
1097 scaley = scalex / aspect_correction;
1100 if (command.corner == BottomRight || command.corner == BottomLeft || command.corner == BottomMiddle)
1102 ty -= imageheight * scaley;
1105 if (command.corner == BottomRight || command.corner == TopRight)
1107 tx -= imagewidth * scalex;
1110 if (command.corner == BottomMiddle || command.corner == TopMiddle)
1112 tx -= imagewidth * scalex * 0.5f;
1115 vgTranslate(tx, ty);
1116 //vgScale(command.w/imagewidth,command.h/imageheight);
1117 vgScale(scalex, scaley);
1118 vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
1119 vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
1120 //Log::getInstance()->log("OSD", Log::DEBUG, "TVMedia Draw Image Scale %g %g %g %g %g %g",command.w,imagewidth,command.h,imageheight,scalex,scaley);
1124 //vgTranslate(200.f,500.f);
1125 //vgScale(100.f,100.f);
1127 vgDrawImage(static_cast<VGImage>(command.target.image));
1129 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw Image %d %x %g %g %g %g %x",command.handle,command.target.image,command.x,command.y,command.w,command.h,
1133 vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
1134 vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER);
1135 vgLoadMatrix(save_matrix2);
1138 vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);
1140 vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
1141 vgLoadMatrix(save_matrix);
1146 vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE);
1147 vgGetMatrix(save_matrix);
1148 vgSetPaint(static_cast<VGPaint>(command.handle), VG_FILL_PATH);
1149 vgSetPaint(static_cast<VGPaint>(command.handle), VG_STROKE_PATH);
1150 vgTranslate(command.x, command.y);
1151 vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER);
1152 vgGetMatrix(save_matrix2);
1153 unsigned int glyph_index = FT_Get_Char_Index(ft_face, command.target.textchar);
1154 vgScale(font_exp_x[glyph_index], font_height);
1156 VGfloat gori[] = {0., 0.};
1157 vgSetfv(VG_GLYPH_ORIGIN, 2, gori);
1159 vgDrawGlyph(vgfont, glyph_index, VG_FILL_PATH, VG_FALSE);
1160 //vgDrawPath(std_paths[Rectangle],VG_FILL_PATH);
1161 /* Log::getInstance()->log("OSD", Log::DEBUG, "Draw Glyph %d %c %d %g %g %x",command.handle,command.target.textchar,glyph_index,command.x,command.y,
1163 vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE);
1164 vgLoadMatrix(save_matrix);
1165 vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER);
1166 vgLoadMatrix(save_matrix2);
1168 vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
1173 cTeletextChar tchar;
1174 tchar.setInternal(command.target.ttchar);
1175 vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE);
1176 vgGetMatrix(save_matrix);
1177 enumTeletextColor ttforegcolour = tchar.GetFGColor();
1178 enumTeletextColor ttbackgcolour = tchar.GetBGColor();
1180 if (tchar.GetBoxedOut())
1182 ttforegcolour = ttcTransparent;
1183 ttbackgcolour = ttcTransparent;
1186 vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_STENCIL);
1187 vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
1189 vgTranslate(command.x + command.w * 11.85f * 1.4f, command.y + command.h * 19.75f);
1190 VGfloat gori[] = {0., 0.};
1191 vgSetfv(VG_GLYPH_ORIGIN, 2, gori);
1193 vgScale(-1.4f, 2.f);
1194 unsigned int color = Surface::enumTeletextColorToCoulour(ttbackgcolour).rgba();
1195 color = color << 8 | (color & 0xff000000) >> 24;
1196 vgSetColor(vgttpaint, color);
1197 vgSetPaint(static_cast<VGPaint>(vgttpaint), VG_FILL_PATH);
1198 vgSetPaint(static_cast<VGPaint>(vgttpaint), VG_STROKE_PATH);
1199 cTeletextChar filled;
1200 filled.setInternal(0x187f);
1201 unsigned int glyph_index = loadTTchar(filled);
1202 vgDrawGlyph(vgttfont, glyph_index, VG_FILL_PATH, VG_FALSE);
1204 color = Surface::enumTeletextColorToCoulour(ttforegcolour).rgba();
1205 color = color << 8 | (color & 0xff000000) >> 24;
1206 vgSetColor(vgttpaint, color);
1207 vgSetPaint(static_cast<VGPaint>(vgttpaint), VG_FILL_PATH);
1208 vgSetPaint(static_cast<VGPaint>(vgttpaint), VG_STROKE_PATH);
1209 glyph_index = loadTTchar(tchar);
1210 vgDrawGlyph(vgttfont, glyph_index, VG_FILL_PATH, VG_FALSE);
1212 /* Log::getInstance()->log("OSD", Log::DEBUG, "Draw TTchar %x %x %x %x",glyph_index,ttforegcolour,Surface::enumTeletextColorToCoulour(ttforegcolour).rgba(),
1213 vgGetColor(vgttpaint));*/
1215 vgLoadMatrix(save_matrix);
1216 vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
1217 vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
1218 vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);
1223 VGint coords[4] = {0, 0, 0, 0};
1224 coords[0] = ((command.x + clip_shift_x) * ((float)BACKBUFFER_WIDTH) / 720.f);
1225 coords[1] = ((576.f - command.y - clip_shift_y - command.h) * ((float)BACKBUFFER_HEIGHT) / 576.f);
1226 coords[2] = ((command.w - 1.f) * ((float)BACKBUFFER_WIDTH) / 720.f);
1227 coords[3] = ((command.h - 1.f) * ((float)BACKBUFFER_HEIGHT) / 576.f);
1228 vgSetiv(VG_SCISSOR_RECTS, 4, coords);
1230 if (command.w == 0.f && command.h == 0.f)
1231 vgSeti(VG_SCISSORING, VG_FALSE);
1233 vgSeti(VG_SCISSORING, VG_TRUE);
1237 case DrawImageLoading:
1243 //int imcount=0;// this is debug code and should not go into release
1244 unsigned int OsdOpenVG::handleTask(OpenVGCommand& command)
1246 switch (command.task)
1248 case OVGreplacefont:
1250 vgDestroyFont(vgfont);
1254 case OVGdestroyImageRef: //imcount--;
1256 //Log::getInstance()->log("OSD", Log::DEBUG, "TVMedia Draw Image Destroy %x %d",command.param1,imcount);
1257 vgDestroyImage(static_cast<VGImage>(command.param1));
1260 case OVGdestroyPaint:
1262 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw Paint Destroy %d ",command.param1);
1263 vgDestroyPaint(static_cast<VGPaint>(command.param1));
1266 case OVGcreateImagePalette: //imcount++;
1268 VGImage input = vgCreateImage(VG_A_8, command.param1, command.param2,
1269 VG_IMAGE_QUALITY_NONANTIALIASED |
1270 VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_BETTER);
1271 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw create palette %d %d %x %d",command.param1,command.param2,vgGetError(),input);
1272 vgImageSubData(input, command.data, command.param1,
1273 VG_A_8, 0, 0, command.param1, command.param2); // upload palettized image data
1274 VGImage handle = vgCreateImage(VG_sRGBA_8888, command.param1, command.param2,
1275 VG_IMAGE_QUALITY_NONANTIALIASED |
1276 VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_BETTER);
1277 VGuint* palette = static_cast<VGuint*>(malloc(256 * sizeof(VGuint)));
1278 const VGuint* in_palette = static_cast<const VGuint*>(command.data2);
1280 for (int i = 0; i < 256; i++)
1282 VGuint color = in_palette[i];
1283 palette[i] = color << 8 | (color & 0xff000000) >> 24;
1286 vgLookupSingle(handle, input, palette, VG_ALPHA, VG_FALSE, VG_FALSE);
1288 vgDestroyImage(input);
1292 case OVGcreateMonoBitmap: //imcount++;
1294 VGImage handle = vgCreateImage(VG_A_1, command.param1, command.param2,
1295 VG_IMAGE_QUALITY_FASTER);
1296 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw create mono %d %d %x %d",command.param1,command.param2,vgGetError(),handle);
1297 unsigned int buffer_len = (command.param1 * command.param2) >> 3;
1298 unsigned char* buffer = static_cast<unsigned char*>(malloc(buffer_len));
1299 unsigned char* r_buffer1 = buffer;
1300 const unsigned char* r_buffer2 = static_cast<const unsigned char*>(command.data);
1301 unsigned char* buffer_end = buffer + buffer_len;
1303 while (r_buffer1 != buffer_end)
1305 unsigned char byte = *r_buffer2;
1306 *r_buffer1 = ((byte * 0x0802LU & 0x22110LU) | (byte * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
1307 r_buffer1++; r_buffer2++;
1310 vgImageSubData(handle, buffer, command.param1 >> 3, VG_A_1, 0, 0, command.param1, command.param2);
1312 // Log::getInstance()->log("OSD", Log::DEBUG, "Draw create mono2 %d %d %x %d",command.param1,command.param2,vgGetError(),handle);
1315 /*case OVGcreateImageFile: {
1318 Image *imagefile=(Image*)command.data;
1320 imagefile->write(&imageblob,"RGBA");
1322 handle=vgCreateImage(VG_sXBGR_8888,imagefile->columns(),imagefile->rows(),
1323 VG_IMAGE_QUALITY_BETTER);
1324 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw create image details %d %d %x mark1",imagefile->columns(),imagefile->rows(),(unsigned int*)imageblob.data());
1325 vgImageSubData(handle,imageblob.data(),imagefile->columns()*4,
1326 VG_sXBGR_8888,0,0,imagefile->columns(),imagefile->rows());
1327 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw create image details %d %d %x mark2",imagefile->columns(),imagefile->rows(),(unsigned int*)imageblob.data());
1329 }catch( Exception &error_ )
1331 Log::getInstance()->log("OSD", Log::DEBUG, "Libmagick hT: %s",error_.what());
1336 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw create file %d %d %x %d",command.param1,command.param2,vgGetError(),handle);
1339 case OVGcreateImageMemory: //imcount++;
1341 const PictureInfo* info = static_cast<const PictureInfo*>(command.data);
1343 //Log::getInstance()->log("OSD", Log::DEBUG, "TVMedia OVGcreateImageMemory %d",imcount);
1344 handle = vgCreateImage(VG_sABGR_8888, info->width, info->height, VG_IMAGE_QUALITY_BETTER);
1345 vgImageSubData(handle, info->image, info->width * 4,
1346 VG_sABGR_8888, 0, 0, info->width, info->height);
1347 info->decoder->freeReference(info->reference);
1349 bool static_image = true;
1351 if (info->lindex & 0xffffffff) static_image = false;
1353 Message* m = new Message();
1354 // We have a pictures! send a message to ourself, to switch to gui thread
1356 m->p_to = Message::CONTROL;
1357 m->data = reinterpret_cast<void*>(handle);
1361 m->message = Message::NEW_PICTURE;
1362 m->tag = info->lindex;
1366 m->message = Message::NEW_PICTURE_STATIC;
1367 m->tag = info->lindex >> 32LL;
1370 MessageQueue::getInstance()->postMessage(m); // inform control about new picture
1375 case OVGcreateEGLImage: //imcount++;
1377 PictureInfo* info = const_cast<PictureInfo*>(static_cast<const PictureInfo*>(command.data));
1380 handle = vgCreateImage(VG_sABGR_8888, info->width, info->height, VG_IMAGE_QUALITY_BETTER);
1381 // Log::getInstance()->log("OSD", Log::DEBUG, "TVMedia OVGcreateEGLImage %d %d %x %d",info->width,info->height, handle,imcount);
1383 info->handle = handle;
1384 info->reference = eglCreateImageKHR(egl_display, egl_context, EGL_VG_PARENT_IMAGE_KHR, reinterpret_cast<EGLClientBuffer>(handle), NULL);
1385 if (info->reference) return true;
1387 Log::getInstance()->log("OSD", Log::DEBUG, "TVMedia OVGcreateEGLImage %d %d %x Fail!", info->width, info->height, handle);
1388 if (handle) vgDestroyImage(handle);
1391 case OVGreadyEGLImage:
1393 PictureInfo* info = const_cast<PictureInfo*>(static_cast<const PictureInfo*>(command.data));
1394 eglDestroyImageKHR(egl_display, info->reference);
1395 bool static_image = true;
1397 if (info->lindex & 0xffffffff) static_image = false;
1399 Message* m = new Message();
1401 m->p_to = Message::CONTROL;
1402 m->data = reinterpret_cast<void*>(info->handle);
1406 m->message = Message::NEW_PICTURE;
1407 m->tag = info->lindex;
1411 m->message = Message::NEW_PICTURE_STATIC;
1412 m->tag = info->lindex >> 32LL;
1415 MessageQueue::getInstance()->postMessage(m); // inform command about new picture
1420 case OVGcreateColorRef:
1423 handle = vgCreatePaint();
1424 const DrawStyle* style = static_cast<const DrawStyle*>(command.data);
1428 case DrawStyle::Color:
1430 vgSetParameteri(handle, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
1431 vgSetColor(handle, command.param1);
1433 //rgba = vgGetColor((VGPaint)handle);
1434 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw Paint %d %x %x",handle,command.param1,rgba);
1437 case DrawStyle::GradientLinear:
1439 vgSetParameteri(handle, VG_PAINT_TYPE, VG_PAINT_TYPE_LINEAR_GRADIENT);
1440 VGfloat params[] = {style->x1, style->y1, style->x2, style->y2, style->r};
1441 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw Gradient %d %g %g %g %g",handle,params[0],params[1],params[2],params[3]);
1442 vgSetParameterfv(handle, VG_PAINT_LINEAR_GRADIENT, 4, params);
1445 case DrawStyle::GradientRadial:
1447 vgSetParameteri(handle, VG_PAINT_TYPE, VG_PAINT_TYPE_RADIAL_GRADIENT);
1448 VGfloat params[] = {style->x1, style->y1, style->x2, style->y2, style->r};
1449 vgSetParameterfv(handle, VG_PAINT_RADIAL_GRADIENT, 5, params);
1454 if (style->ft == DrawStyle::GradientLinear || style->ft == DrawStyle::GradientRadial)
1456 VGfloat colorramp[5 * 5];
1457 colorramp[0 + 0 * 5] = 0.f;
1458 colorramp[1 + 0 * 5] = style->red / 255.f;
1459 colorramp[2 + 0 * 5] = style->green / 255.f;
1460 colorramp[3 + 0 * 5] = style->blue / 255.f;
1461 colorramp[4 + 0 * 5] = style->alpha / 255.f;
1463 for (int i = 0; i < (style->num_colors - 1); i++)
1465 colorramp[0 + (i + 1) * 5] = style->grad_pos[i];
1466 colorramp[1 + (i + 1) * 5] = style->grad_col[i].red / 255.f;
1467 colorramp[2 + (i + 1) * 5] = style->grad_col[i].green / 255.f;
1468 colorramp[3 + (i + 1) * 5] = style->grad_col[i].blue / 255.f;
1469 colorramp[4 + (i + 1) * 5] = style->grad_col[i].alpha / 255.f;
1472 colorramp[0 + (style->num_colors) * 5] = 1.f;
1473 colorramp[1 + (style->num_colors) * 5] = style->grad_col[style->num_colors - 1].red / 255.f;
1474 colorramp[2 + (style->num_colors) * 5] = style->grad_col[style->num_colors - 1].green / 255.f;
1475 colorramp[3 + (style->num_colors) * 5] = style->grad_col[style->num_colors - 1].blue / 255.f;
1476 colorramp[4 + (style->num_colors) * 5] = style->grad_col[style->num_colors - 1].alpha / 255.f;
1477 vgSetParameteri(handle, VG_PAINT_COLOR_RAMP_SPREAD_MODE, VG_COLOR_RAMP_SPREAD_REFLECT);
1478 vgSetParameteri(handle, VG_PAINT_COLOR_RAMP_PREMULTIPLIED, VG_FALSE);
1479 vgSetParameterfv(handle, VG_PAINT_COLOR_RAMP_STOPS, 5 + (style->num_colors) * 5, colorramp);
1485 case OVGimageUploadLine:
1492 bool OsdOpenVG::processTasks()
1494 bool worked = false;
1498 while (vgcommands.size() > 0)
1500 OpenVGCommand comm = vgcommands.front();
1501 vgcommands.pop_front();
1504 OpenVGResponse resp;
1505 resp.result = handleTask(comm);
1511 vgresponses.push_back(resp);
1517 /* Getting rid of Signal class. As with VideoOMX, just replicate what Signal did here
1518 * and figure out if any of this can be simplified later. e.g. taskmutex sounds
1519 * like it should be the mutex being used. 3 mutexes here???
1522 vgTaskSignalMutex.lock();
1523 vgTaskSignal.notify_one();
1524 vgTaskSignalMutex.unlock();
1537 unsigned int OsdOpenVG::putOpenVGCommand(OpenVGCommand& comm, bool wait)
1542 comm.id = wait_id++;
1544 comm.id = 0; // we are not waiting
1546 vgcommands.push_back(comm);
1551 if (!wait) return 0;
1555 // Is there a response now?
1557 for (auto& vgresponse : vgresponses)
1559 if (vgresponse.id == comm.id)
1561 UINT resp = vgresponse.result;
1569 std::unique_lock<std::mutex> ul(vgTaskSignalMutex);
1570 vgTaskSignal.wait_for(ul, std::chrono::milliseconds(100));
1575 void OsdOpenVG::destroyImageRef(ImageIndex index)
1577 struct OpenVGCommand comm;
1578 comm.task = OVGdestroyImageRef;
1579 comm.param1 = index;
1580 putOpenVGCommand(comm, false);
1583 bool OsdOpenVG::getStaticImageData(unsigned int static_id, UCHAR** userdata, ULONG* length)
1585 if (sa_MAX > static_id)
1587 *userdata = static_artwork_begin[static_id];
1588 *length = static_artwork_end[static_id] - static_artwork_begin[static_id];
1597 void OsdOpenVG::createPicture(struct PictureInfo& pict_inf)
1599 struct OpenVGCommand comm;
1600 Log::getInstance()->log("OsdOpenVG", Log::DEBUG, "TVMedia Create Picture %d", pict_inf.type);
1602 if (pict_inf.type == PictureInfo::RGBAMemBlock)
1604 comm.task = OVGcreateImageMemory;
1605 comm.data = new PictureInfo(pict_inf);
1606 putOpenVGCommand(comm, false);
1608 else if (pict_inf.type == PictureInfo::EGLImage)
1610 comm.task = OVGreadyEGLImage;
1611 comm.data = new PictureInfo(pict_inf);
1612 putOpenVGCommand(comm, false);
1617 pict_inf.decoder->freeReference(pict_inf.reference);
1621 bool OsdOpenVG::getEGLPicture(struct OsdVector::PictureInfo& info, EGLDisplay* display)
1623 struct OpenVGCommand comm;
1624 info.type = PictureInfo::EGLImage;
1625 comm.task = OVGcreateEGLImage;
1627 *display = egl_display;
1628 return putOpenVGCommand(comm, true);
1631 ImageIndex OsdOpenVG::createMonoBitmap(void* base, int width, int height)
1633 struct OpenVGCommand comm;
1634 comm.task = OVGcreateMonoBitmap;
1635 comm.param1 = width;
1636 comm.param2 = height;
1638 return putOpenVGCommand(comm, true);
1641 ImageIndex OsdOpenVG::createImagePalette(int width, int height, const unsigned char* image_data, const unsigned int* palette_data)
1643 struct OpenVGCommand comm;
1644 comm.task = OVGcreateImagePalette;
1645 comm.param1 = width;
1646 comm.param2 = height;
1647 comm.data = image_data;
1648 comm.data2 = palette_data;
1649 return putOpenVGCommand(comm, true);
1652 void OsdOpenVG::destroyDrawStyleHandle(VectorHandle index)
1654 struct OpenVGCommand comm;
1655 comm.task = OVGdestroyPaint;
1656 comm.param1 = index;
1657 putOpenVGCommand(comm, false);
1660 VectorHandle OsdOpenVG::createDrawStyleHandle(const DrawStyle& c)
1662 unsigned int col = c.rgba();
1663 struct OpenVGCommand comm;
1664 comm.task = OVGcreateColorRef;
1665 comm.param1 = col << 8 | (col & 0xff000000) >> 24;
1667 return putOpenVGCommand(comm, true);