]> git.vomp.tv Git - vompclient.git/blob - osdopenvg.cc
Fix shutdown of osdvector and some hdmi related changes#
[vompclient.git] / osdopenvg.cc
1 /*
2     Copyright 2004-2005 Chris Tallon, 2006,2011-2012 Marten Richter
3
4     This file is part of VOMP.
5
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.
10
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.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21
22 #include "osdopenvg.h"
23 #include "mtd.h"
24 #include "videoomx.h"
25 #include "surface.h"
26 #include <Magick++.h>
27
28 #include "message.h"
29 #include "command.h"
30 #include "teletxt/txtfont.h"
31
32 #include <sys/syscall.h>
33 #include <vector>
34 #include <math.h>
35
36 using namespace Magick;
37
38 extern uint8_t font_data[]     asm("_binary_fonts_sourcesans_ttf_start");
39 extern uint8_t font_data_end[] asm("_binary_fonts_sourcesans_ttf_end");
40 extern uint8_t vdr_data[]     asm("_binary_other_vdrhires_jpg_start");
41 extern uint8_t vdr_data_end[] asm("_binary_other_vdrhires_jpg_end");
42 extern uint8_t wallpaper_data[]     asm("_binary_other_wallpaper720p_jpg_start");
43 extern uint8_t wallpaper_data_end[] asm("_binary_other_wallpaper720p_jpg_end");
44
45
46 #define  BACKBUFFER_WIDTH 1280
47 #define  BACKBUFFER_HEIGHT 720
48
49
50 OsdOpenVG::OsdOpenVG()
51 {
52   vgmutex.Lock();
53   taskmutex.Lock();
54   lastrendertime=getTimeMS();
55   display_height=0;
56   display_width=0;
57   mode=0;
58   aspect_correction=1.;
59
60   freetype_inited=false;
61   wait_id=1;
62
63 }
64
65 OsdOpenVG::~OsdOpenVG()
66 {
67
68   if (initted)
69   {
70                 shutdown();
71   }
72
73   if (freetype_inited) FT_Done_Face(ft_face);
74
75   vgmutex.Unlock();
76   taskmutex.Unlock();
77 }
78
79
80
81 int OsdOpenVG::init(void* device)
82 {
83   if (initted) return 0;
84   Video* video = Video::getInstance();
85    //window=*((HWND*)device);
86
87    // May be this device specific part should go to a device specific child class
88
89    //init broadcom chipset (Move to video?)
90
91
92    //First get connection to egl
93    egl_display=eglGetDisplay(EGL_DEFAULT_DISPLAY);
94
95    if (egl_display==EGL_NO_DISPLAY) {
96            Log::getInstance()->log("OSD", Log::WARN, "Could not get egl display! %x",eglGetError());
97            vgmutex.Unlock();
98            return 0;
99    }
100
101
102
103    if (eglInitialize(egl_display, NULL, NULL)==EGL_FALSE) {
104            Log::getInstance()->log("OSD", Log::WARN, "Initialising display failed! %x",eglGetError());
105            vgmutex.Unlock();
106            return 0;
107    }
108
109
110    const char *query_str=eglQueryString(egl_display,EGL_CLIENT_APIS);
111    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
112    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",eglGetError());
113    query_str=eglQueryString(egl_display,EGL_EXTENSIONS);
114    if (query_str)    Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
115    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",eglGetError());
116
117    if (eglBindAPI(EGL_OPENVG_API)==EGL_FALSE) {
118            Log::getInstance()->log("OSD", Log::WARN, "Binding openvg api failed! %x",eglGetError());
119            vgmutex.Unlock();
120            return 0;
121    }
122
123    const EGLint attributs[]={
124                  EGL_RED_SIZE,8,EGL_GREEN_SIZE, 8,EGL_BLUE_SIZE, 8,EGL_ALPHA_SIZE, 8,
125          EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT,
126          EGL_CONFORMANT, EGL_OPENVG_BIT,
127          EGL_NONE
128    }; // Here, we might have to select the resolution!
129
130
131    EGLint number;
132
133    if (eglChooseConfig(egl_display, attributs, &egl_ourconfig, 1, &number)==EGL_FALSE) {
134            Log::getInstance()->log("OSD", Log::WARN, "Choosing egl config failed! %x",eglGetError());
135            vgmutex.Unlock();
136            return 0;
137    }
138
139
140
141    egl_context=eglCreateContext(egl_display,egl_ourconfig,NULL,NULL);
142    if (egl_context==EGL_NO_CONTEXT) {
143            Log::getInstance()->log("OSD", Log::WARN, "Creating egl context failed! %x",eglGetError());
144            vgmutex.Unlock();
145            return 0;
146    }
147
148    // warning broadcom specific, get display size!
149    display_width=display_height=0;
150    if (graphics_get_display_size(0, &display_width, &display_height)<0) {
151            Log::getInstance()->log("OSD", Log::WARN, "Getting display size failed! (BCM API) ");
152            vgmutex.Unlock();
153            return 0;
154    }
155    Log::getInstance()->log("OSD", Log::NOTICE, "Displaysize is %d x %d ",display_width, display_height);
156    VC_RECT_T dst_rect ={0,0,display_width,display_height};
157    VC_RECT_T src_rect={0,0,BACKBUFFER_WIDTH <<16,BACKBUFFER_HEIGHT<<16};
158   // VC_RECT_T src_rect_bg={0,0,1<<16,1<<16};
159  //  VC_RECT_T src_rect_im={0,0,1,1};
160
161   /* uint32_t back_image_ptr;
162    bcm_backres=vc_dispmanx_resource_create(VC_IMAGE_RGB888,1,1,&back_image_ptr);
163    unsigned int color=0x00FF0000;
164    vc_dispmanx_resource_write_data(bcm_backres,VC_IMAGE_RGB888,4,&color,&src_rect_im);*/
165
166    DISPMANX_UPDATE_HANDLE_T  bcm_update;
167    bcm_display=vc_dispmanx_display_open(0);
168    bcm_update=vc_dispmanx_update_start(0);
169    bcm_element=vc_dispmanx_element_add(bcm_update,bcm_display,
170          2,&dst_rect, 0,
171          &src_rect,DISPMANX_PROTECTION_NONE,0, 0, (DISPMANX_TRANSFORM_T) 0);
172
173
174  /*  bcm_background=vc_dispmanx_element_add(bcm_update,bcm_display,
175             0,&dst_rect,bcm_backres ,
176             &src_rect_bg,DISPMANX_PROTECTION_NONE,0, 0, (DISPMANX_TRANSFORM_T) 0);*/
177
178    vc_dispmanx_update_submit_sync(bcm_update);
179
180
181
182    static EGL_DISPMANX_WINDOW_T nativewindow;
183    nativewindow.element=bcm_element;
184    nativewindow.height=BACKBUFFER_HEIGHT;
185    nativewindow.width=BACKBUFFER_WIDTH;
186
187    egl_surface = eglCreateWindowSurface(egl_display,egl_ourconfig, &nativewindow,NULL );
188    if (egl_surface==EGL_NO_SURFACE) {
189            Log::getInstance()->log("OSD", Log::WARN, "Creating egl window surface failed!");
190            vgmutex.Unlock();
191            return 0;
192    }
193    Log::getInstance()->log("OSD", Log::DEBUG, "Making egl current in1%d",syscall(SYS_gettid));
194    if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) {
195            Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed");
196            vgmutex.Unlock();
197                    return 0;
198    }
199    // Test stuff
200
201    query_str=(const char*)vgGetString(VG_VERSION) ;
202    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
203    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",vgGetError());
204
205    query_str=(const char*)vgGetString(VG_VENDOR) ;
206    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
207    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",vgGetError());
208
209    query_str=(const char*)vgGetString(VG_RENDERER) ;
210    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
211    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",vgGetError());
212
213    query_str=(const char*)vgGetString(VG_EXTENSIONS) ;
214    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
215    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",vgGetError());
216
217   aspect_correction= ((float)BACKBUFFER_HEIGHT)/576.f/(((float)BACKBUFFER_WIDTH)/720.f);
218   initPaths();
219   if (!loadFont()) {
220           return 0;
221   }
222   vgttfont=vgCreateFont(0);
223   vgttpaint=vgCreatePaint();
224   vgSetParameteri( vgttpaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
225   vgSetColor(vgttpaint,0xffffffff);
226
227   eglSwapInterval(egl_display, 1 );
228
229   Log::getInstance()->log("OSD", Log::DEBUG, "Making egl current out 1%d",syscall(SYS_gettid));
230   eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
231   //Now we will create the Screen
232   initted = 1; // must set this here or create surface won't work
233
234
235   /*if (((VideoOMX*)Video::getInstance())->initUsingOSDObjects()!=1) { //call Video for init  stuff
236           return 0;
237   }*/
238   InitializeMagick("");
239
240   pthread_cond_init(&vgtaskCond, NULL);
241   pthread_mutex_init(&vgtaskCondMutex, NULL);
242
243   threadStart();
244   taskmutex.Unlock();
245   vgmutex.Unlock();
246
247
248   return 1;
249 }
250
251
252 void OsdOpenVG::initPaths()
253 {
254
255
256         VGPath current;
257         current=vgCreatePath(VG_PATH_FORMAT_STANDARD,
258                         VG_PATH_DATATYPE_F,1.f,0.f,
259                         0,0,VG_PATH_CAPABILITY_ALL);
260
261         vguLine(current,0.f,0.f,1.f,0.f);
262         // HorzLine
263         std_paths[HorzLine]=current;
264
265         current=vgCreatePath(VG_PATH_FORMAT_STANDARD,
266                                 VG_PATH_DATATYPE_F,1.f,0.f,
267                                 0,0,VG_PATH_CAPABILITY_ALL);
268         vguLine(current,0.f,0.f,0.f,1.f);
269         // VertLine
270         std_paths[VertLine]=current;
271
272         current=vgCreatePath(VG_PATH_FORMAT_STANDARD,
273                                 VG_PATH_DATATYPE_F,1.f,0.f,
274                                 0,0,VG_PATH_CAPABILITY_ALL);
275         //vguRect(current,0.f,0.f,1.f,1.f);
276         vguRect(current,0.f,0.f,1.f,1.f);
277         // Rectabgle
278         std_paths[Rectangle]=current;
279
280         current=vgCreatePath(VG_PATH_FORMAT_STANDARD,
281                                 VG_PATH_DATATYPE_F,1.f,0.f,
282                                 0,0,0);
283         vguEllipse(current,0.f,0.f,1.f,1.f);
284         // Point
285         std_paths[Point]=current;
286
287 }
288
289 void OsdOpenVG::destroyPaths()
290 {
291         vgDestroyPath(std_paths[HorzLine]);
292         vgDestroyPath(std_paths[VertLine]);
293         vgDestroyPath(std_paths[Rectangle]);
294         vgDestroyPath(std_paths[Point]);
295
296 }
297
298 int OsdOpenVG::stopUpdate()
299 {
300         threadStop();
301         processTasks();
302         return 1;
303 }
304
305 void OsdOpenVG::purgeAllReferences()
306 {
307         images_ref.clear();
308         styles_ref.clear(); // remove all references
309
310
311         map<void *,ImageIndex>::iterator mitty=monobitmaps.begin();
312         while (mitty!=monobitmaps.end()) {
313                 vgDestroyImage((VGImage)(*mitty).second);
314                 mitty++;
315         }
316         monobitmaps.clear();
317
318         map<string,ImageIndex>::iterator jitty=jpegs.begin();
319         while (jitty!=jpegs.end()) {
320                 vgDestroyImage((VGImage)(*jitty).second);
321                 jitty++;
322         }
323         jpegs.clear();
324
325         map<pair<Colour*,unsigned int>,unsigned int>::iterator sitty=styles.begin();
326         while (sitty!=styles.end()) {
327                 vgDestroyPaint((VGPaint)(*sitty).second);
328                 sitty++;
329         }
330         styles.clear();
331
332 }
333
334 int OsdOpenVG::shutdown()
335 {
336   if (!initted) return 0;
337
338   initted = 0;
339   Log::getInstance()->log("OSD", Log::DEBUG, "shutdown mark1");
340   threadStop();
341   Log::getInstance()->log("OSD", Log::DEBUG, "shutdown mark1a");
342   //(((VideoOMX*)Video::getInstance())->shutdownUsingOSDObjects());
343   if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) {
344           Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed in shutdown %x",eglGetError());
345   }
346   if (eglBindAPI(EGL_OPENVG_API)==EGL_FALSE) {
347           Log::getInstance()->log("OSD", Log::WARN, "Binding openvg api thread failed! %x",eglGetError());
348   }
349
350   Log::getInstance()->log("OSD", Log::DEBUG, "shutdown mark2");
351   processTasks();
352   Log::getInstance()->log("OSD", Log::DEBUG, "shutdown mark3");
353
354   taskmutex.Lock();
355   vgmutex.Lock();
356
357
358
359   //purgeAllReferences();
360
361   vgDestroyFont(vgfont);
362   vgDestroyFont(vgttfont);
363   vgDestroyPaint(vgttpaint);
364   destroyPaths();
365   float colclear[]={0.8f,0.8f,0.8f,1.f};
366   vgSetfv(VG_CLEAR_COLOR,4,colclear);
367   vgClear(0,0,BACKBUFFER_WIDTH,BACKBUFFER_HEIGHT);
368   eglSwapBuffers(egl_display, egl_surface);
369   Log::getInstance()->log("OSD", Log::DEBUG, "Making egl current out final");
370   eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
371   if (eglDestroySurface(egl_display,egl_surface)==EGL_FALSE) {
372           Log::getInstance()->log("OSD", Log::ERR, "eglDestroySurface failed %x",eglGetError());
373   }
374   if (eglDestroyContext(egl_display,egl_context)==EGL_FALSE) {
375           Log::getInstance()->log("OSD", Log::ERR, "eglDestroyContext failed %x",eglGetError());
376   }
377   if (eglTerminate(egl_display )==EGL_FALSE) {
378           Log::getInstance()->log("OSD", Log::ERR, "eglTerminate failed %x",eglGetError());
379   }
380
381   DISPMANX_UPDATE_HANDLE_T  bcm_update;
382   bcm_update=vc_dispmanx_update_start(0);
383
384   vc_dispmanx_element_remove(bcm_update,bcm_element);
385 //  vc_dispmanx_element_remove(bcm_update,bcm_background);
386   vc_dispmanx_update_submit_sync(bcm_update);
387 //  vc_dispmanx_resource_delete(bcm_backres);
388   vc_dispmanx_display_close(bcm_display);
389
390
391
392   return 1;
393 }
394
395
396
397
398 void OsdOpenVG::threadMethod()
399 {
400         // We have to claim the egl context for this thread
401         Log::getInstance()->log("OSD", Log::NOTICE, "Entering drawing thread");
402         if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) {
403                 Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed in thread %x",eglGetError());
404                 return;
405         }
406         if (eglBindAPI(EGL_OPENVG_API)==EGL_FALSE) {
407                 Log::getInstance()->log("OSD", Log::WARN, "Binding openvg api thread failed! %x",eglGetError());
408                 return;
409         }
410         int ts=0;
411         while (true)
412         {
413                 ts=1;
414                 unsigned int waittime=1;
415
416                 if (initted) {
417
418                         long long time1 = getTimeMS();
419                         if ((time1 - lastrendertime) > 200) {//5 fps for OSD updates are enough, avoids tearing
420                                 InternalRendering();
421                                 lastrendertime = getTimeMS();
422
423                         }
424                         if (processTasks()) ts=0;
425                 }
426                 if (!threadIsActive()) {
427                         if (eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT )== EGL_FALSE) {
428                                    Log::getInstance()->log("OSD", Log::WARN, "Making egl Current out thread failed");
429                         }
430                         threadCheckExit();
431                 }
432                 if (ts!=0) {
433                         struct timespec target_time;
434                         clock_gettime(CLOCK_REALTIME,&target_time);
435                         target_time.tv_nsec+=1000000LL*ts;
436                         if (target_time.tv_nsec>999999999) {
437                                 target_time.tv_nsec-=1000000000L;
438                                 target_time.tv_sec+=1;
439                         }
440                         threadLock();
441                         threadWaitForSignalTimed(&target_time);
442                         threadUnlock();
443                 }
444                 //Sleep(1);
445         }
446         eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
447 }
448
449
450 void OsdOpenVG::threadPostStopCleanup()
451 {
452         //Doing nothing
453         //goo;
454         Log::getInstance()->log("OSD", Log::NOTICE, "Exiting drawing thread");
455 }
456
457 void OsdOpenVG::InternalRendering(){
458         vgmutex.Lock();
459     float colclear[]={1.f,1.0f,1.f,1.f};
460     vgSetfv(VG_CLEAR_COLOR,4,colclear);
461         vgClear(0,0,BACKBUFFER_WIDTH,BACKBUFFER_HEIGHT);
462         vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);
463
464
465         drawSurfaces(); //iterate through and draws all commands
466
467         //Show it to the user!
468         eglSwapBuffers(egl_display, egl_surface);
469         vgmutex.Unlock();
470
471 }
472
473 /*font stuff*/
474
475 float OsdOpenVG::getFontHeight()
476 {
477         return font_height; //dummy
478 }
479 float OsdOpenVG::getCharWidth(wchar_t c)
480 {
481         unsigned int glyph_index=FT_Get_Char_Index(ft_face,c);
482         return font_exp_x[glyph_index];
483 }
484
485 unsigned int OsdOpenVG::loadTTchar(cTeletextChar c)
486 {
487         unsigned int glyph_index=c.getGlyphIndex();
488         if (tt_font_chars.find(glyph_index)!=tt_font_chars.end())
489         {
490                 return glyph_index;
491         }
492
493         unsigned int buffer[10];
494         const VGfloat glyphOrigin[] = { 0.f, 0.f };
495         const VGfloat escapement[] = { 12.f, 0.f };
496         unsigned int * charmap = GetFontChar(c, buffer);
497         if (!charmap) { //invalid char
498                 return 0;
499         }
500         for (int i=0;i<10;i++) {
501                 buffer[i]=charmap[i]>>4;
502         }
503
504         VGImage handle = vgCreateImage(
505                         VG_A_8,
506                         12,
507                         10,
508                         VG_IMAGE_QUALITY_NONANTIALIASED | VG_IMAGE_QUALITY_FASTER
509                                         | VG_IMAGE_QUALITY_BETTER);
510         vgImageSubData(handle, buffer, 4, VG_A_1, 0, 0, 12, 10);
511         vgSetGlyphToImage(
512                         vgttfont,
513                         glyph_index,
514                         handle, glyphOrigin, escapement);
515         vgDestroyImage(handle);
516         tt_font_chars[glyph_index]=1;
517
518         return glyph_index;
519 }
520
521 int  OsdOpenVG::loadFont()
522 {
523         int error;
524         float font_size=16.f;
525         if (!freetype_inited) {
526                 error=FT_Init_FreeType(&ft_library);
527                 if (error)
528                 {
529                         Log::getInstance()->log("OSD", Log::WARN, "Could not load freetype %x",error);
530                         return 0;
531                 }
532
533                 error=FT_New_Memory_Face(ft_library,font_data,font_data_end-font_data,0,&ft_face );
534                 if (error) {
535                         Log::getInstance()->log("OSD", Log::WARN, "Could not load font face %x",error);
536                         return 0;
537                 }
538                 error=FT_Set_Char_Size(ft_face,0,font_size*64,0,0 /*dpi*/);
539                 if (error) {
540                         FT_Done_Face(ft_face);
541                         Log::getInstance()->log("OSD", Log::WARN, "Could not set  face size %x",error);
542                         return 0;
543                 }
544                 freetype_inited=true;
545         }
546         vgfont=vgCreateFont(0);
547         FT_ULong cur_char;
548         FT_UInt glyph;
549         font_height=ft_face->size->metrics.height/64.f;
550         cur_char = FT_Get_First_Char(ft_face,&glyph);
551         vector<VGubyte> segments;
552         vector<VGfloat> coord;
553         segments.reserve(256);
554         coord.reserve(1024);
555         //Log::getInstance()->log("OSD", Log::DEBUG, "Create Glyph test %d %x %x %d",cur_char,font_data_end,font_data,glyph);
556         while (glyph !=0)
557         {
558                 error=FT_Load_Glyph(ft_face,glyph,FT_LOAD_DEFAULT);
559                 if (error){
560                         FT_Done_Face(ft_face);
561                         Log::getInstance()->log("OSD", Log::WARN, "Could not load glyph %x",error);
562                         return 0;
563                 }
564                 VGPath path;
565                 FT_Outline ot=ft_face->glyph->outline;
566                 segments.clear();
567                 coord.clear();
568
569                 if (ot.n_contours ==0) {
570                         path=VG_INVALID_HANDLE;
571                 } else {
572                         path=vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
573                                         1.0f,0.f,0,0,VG_PATH_CAPABILITY_ALL);
574
575                         /* convert glyph */
576                         FT_Vector *pt=ot.points;
577                         const char *tags=ot.tags;
578                         const short* cont=ot.contours;
579                         short n_cont=ot.n_contours;
580                         short n_point=ot.n_points;
581                         short last_cont=0;
582                         for (short point=0;n_cont!=0;cont++,n_cont--) {
583                                 short next_cont=*cont+1;
584                                 bool first=true;
585                                 char last_tag=0;
586                                 short first_point=point;
587                                 //Log::getInstance()->log("OSD", Log::DEBUG, "runs %d",*cont);
588                                 for (;point<next_cont;point++) {
589                                         char tag=tags[point];
590                                         FT_Vector fpoint=pt[point];
591                                 //      Log::getInstance()->log("OSD", Log::DEBUG, "tag %d point %d %d: %d %d",tag,fpoint.x,fpoint.y,point,n_point);
592                                         if (first) {
593                                                 segments.push_back(VG_MOVE_TO);
594                                                 first=false;
595                                         } else if (tag &0x1) { //on curve
596                                                 if (last_tag &0x1) {
597                                                         segments.push_back(VG_LINE_TO);
598                                                 } else if (last_tag &0x2){
599                                                         segments.push_back(VG_CUBIC_TO);
600                                                 } else {
601                                                         segments.push_back(VG_QUAD_TO);
602                                                 }
603
604                                         } else {
605                                                 if (!(tag &0x2)){
606                                                         if (!(last_tag &0x1)) {
607                                                                 segments.push_back(VG_QUAD_TO);
608                                                                 int coord_size=coord.size();
609                                                                 VGfloat x=(coord[coord_size-2]+ ((float)fpoint.x)/64.f)*0.5f*aspect_correction;
610                                                                 VGfloat y=(coord[coord_size-1]+(font_size- ((float)fpoint.y)/64.f))*0.5f;
611                                                                 coord.push_back(x);
612                                                                 coord.push_back(y);
613                                                         }
614                                                 }
615
616
617                                         }
618                                         last_tag=tag;
619                                         coord.push_back(((float)fpoint.x)*aspect_correction/64.);
620                                         coord.push_back(font_size-((float)fpoint.y)/64.);
621                                         //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]);
622                                 }
623                                 if (!(last_tag &0x1)) {
624                                         if (last_tag &0x2) {
625                                                 segments.push_back(VG_CUBIC_TO);
626                                         } else {
627                                                 segments.push_back(VG_QUAD_TO);
628                                         }
629                                         coord.push_back(((float)pt[first_point].x)*aspect_correction/64.);
630                                         coord.push_back(font_size-((float)pt[first_point].y)/64.);
631                                 }
632                                 //segments.push_back(VG_CLOSE_PATH);
633
634
635                         }
636                         vgAppendPathData(path,segments.size(),&segments[0],&coord[0]);
637                         int n=0;
638                 /*      for (int m=0;m<segments.size();m++) {
639                                 switch (segments[m])
640                                 {
641                                 case VG_MOVE_TO:
642                                         Log::getInstance()->log("OSD", Log::DEBUG, "Move To %g %g",coord[n],coord[n+1]);n+=2; break;
643                                 case VG_LINE_TO:
644                                         Log::getInstance()->log("OSD", Log::DEBUG, "Line To %g %g",coord[n],coord[n+1]);n+=2; break;
645                                 case VG_CUBIC_TO:
646                                         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;
647                                 case VG_QUAD_TO:
648                                         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;
649                                 case VG_CLOSE_PATH:
650                                         Log::getInstance()->log("OSD", Log::DEBUG, "Close Path"); break;
651                                 }
652
653                         }*/
654                         //vguRect(path,0.f,0.f,1.f,1.f);
655                         //Log::getInstance()->log("OSD", Log::DEBUG, "Create APD Glyph %d %x",segments.size(),vgGetError());
656                 }
657                 VGfloat ori[]={0.f,0.f};
658                 VGfloat esp[]={ft_face->glyph->advance.x/64.f*aspect_correction,ft_face->glyph->advance.y/64.f};
659                 font_exp_x[glyph]=ft_face->glyph->advance.x/64.f*aspect_correction; //recalculate
660
661                 vgSetGlyphToPath(vgfont,glyph,path,VG_FALSE,ori,esp);
662                 //Log::getInstance()->log("OSD", Log::DEBUG, "Create Glyph %d %d %x",path,glyph,vgGetError());
663                 if (path!=VG_INVALID_HANDLE) {
664                         vgDestroyPath(path);
665                 }
666                 cur_char = FT_Get_Next_Char(ft_face,cur_char,&glyph);
667         }
668         return 1;
669 }
670
671
672 void OsdOpenVG::drawSetTrans(SurfaceCommands & sc)
673 {
674         vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
675         vgLoadIdentity();
676         vgScale(((float)BACKBUFFER_WIDTH)/720.f, -((float)BACKBUFFER_HEIGHT)/576.f);
677         vgTranslate(0.f+sc.x,-576.f+sc.y);
678
679         vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE);
680         vgLoadIdentity();
681     vgScale(((float)BACKBUFFER_WIDTH)/720.f, -((float)BACKBUFFER_HEIGHT)/576.f);
682         vgTranslate(0.f+sc.x,-576.f+sc.y);
683
684         vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
685         vgLoadIdentity();
686         vgScale(((float)BACKBUFFER_WIDTH)/720.f, -((float)BACKBUFFER_HEIGHT)/576.f);
687         vgTranslate(0.f+sc.x,-576.f+sc.y);
688
689
690
691         //vgTranslate(0.f+sc.x,576.f-sc.y);
692         //Log::getInstance()->log("OSD", Log::DEBUG, "Draw Translate %g %g",sc.x,sc.y);
693
694 }
695 void OsdOpenVG::executeDrawCommand(SVGCommand & command)
696 {
697
698         VGfloat  save_matrix[9];
699         switch (command.instr) {
700         case DrawPath: {
701         vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
702         //      VGuint rgba;
703         //      rgba = vgGetColor((VGPaint) command.reference);
704                 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw Path %d %x %g %g %g %g",command.reference,command.target.path_index,command.x,command.y,command.w,command.h);
705                 //vgSeti(VG_FILL_RULE,);
706
707                 vgGetMatrix(save_matrix);
708                 vgSetPaint((VGPaint) command.reference,VG_FILL_PATH);
709                 vgSetPaint((VGPaint) command.reference,VG_STROKE_PATH);
710                 vgTranslate(command.x,command.y);
711                 vgScale(command.w,command.h);
712                 vgDrawPath(std_paths[command.target.path_index],VG_FILL_PATH);
713                 vgLoadMatrix(save_matrix);
714         } break;
715         case DrawImage: {
716             vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
717                 vgGetMatrix(save_matrix);
718                 vgTranslate(command.x,command.y);
719                 //vgScale(command.w,command.h);
720                 if (command.reference) { //special behaviout for bw images they act as a mask on the current paint
721                         vgSetPaint((VGPaint) command.reference,VG_FILL_PATH);
722                         vgSetPaint((VGPaint) command.reference,VG_STROKE_PATH);
723                         vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_STENCIL);
724                         vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
725                         vgScale(aspect_correction,1.f);
726                 } else {
727                         VGfloat imagewidth=vgGetParameteri((VGImage) command.target.image, VG_IMAGE_WIDTH);
728                         VGfloat imageheight=vgGetParameteri((VGImage) command.target.image, VG_IMAGE_HEIGHT);
729                         //vgScale(720.f/((float)BACKBUFFER_WIDTH), 576.f/((float)BACKBUFFER_HEIGHT));
730                         float scalex=command.w/imagewidth;
731                         float scaley=command.h/imageheight;
732                         //vgScale(command.w/imagewidth,command.h/imageheight);
733                         vgScale(scalex,scaley);
734                         vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_NORMAL);
735                         //Log::getInstance()->log("OSD", Log::DEBUG, "Draw Image Scale  %g %g %g %g %g %g",command.w,imagewidth,command.h,imageheight,scalex,scaley);
736                 }
737
738
739                 //vgLoadIdentity();
740                 //vgTranslate(200.f,500.f);
741                 //vgScale(100.f,100.f);
742
743                 vgDrawImage((VGImage) command.target.image);
744                 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw Image %d %x %g %g %g %g %x",command.reference,command.target.image,command.x,command.y,command.w,command.h,
745                 //              vgGetError());
746                 if (command.reference) {
747                         vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_NORMAL);
748                         vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);
749                 }
750                 vgLoadMatrix(save_matrix);
751         } break;
752         case DrawGlyph: {
753                 vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE);
754                 vgGetMatrix(save_matrix);
755                 vgSetPaint((VGPaint) command.reference,VG_FILL_PATH);
756                 vgSetPaint((VGPaint) command.reference,VG_STROKE_PATH);
757                 vgTranslate(command.x,command.y);
758                 VGfloat gori[]={0.,0.};
759                 vgSetfv(VG_GLYPH_ORIGIN,2,gori);
760
761                 unsigned int glyph_index=FT_Get_Char_Index(ft_face,command.target.textchar);
762                 vgDrawGlyph(vgfont,glyph_index,VG_FILL_PATH,VG_FALSE);
763                 //vgDrawPath(std_paths[Rectangle],VG_FILL_PATH);
764         /*      Log::getInstance()->log("OSD", Log::DEBUG, "Draw Glyph %d %c %d %g %g %x",command.reference,command.target.textchar,glyph_index,command.x,command.y,
765                                                 vgGetError());*/
766                 vgLoadMatrix(save_matrix);
767                 vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
768         } break;
769         case DrawTTchar:{
770                 cTeletextChar tchar;
771                 tchar.setInternal(command.target.ttchar);
772                 vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE);
773                 vgGetMatrix(save_matrix);
774                 enumTeletextColor ttforegcolour=tchar.GetFGColor();
775                 enumTeletextColor ttbackgcolour=tchar.GetBGColor();
776             if (tchar.GetBoxedOut()) {
777                 ttforegcolour=ttcTransparent;
778                 ttbackgcolour=ttcTransparent;
779             }
780             vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_STENCIL);
781             vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
782
783
784                 vgTranslate(command.x+command.w*11.85f*1.4f,command.y+command.h*19.75f);
785                 VGfloat gori[]={0.,0.};
786                 vgSetfv(VG_GLYPH_ORIGIN,2,gori);
787
788                 vgScale(-1.4f,2.f);
789                 unsigned int color=Surface::enumTeletextColorToCoulour(ttbackgcolour).rgba();
790                 color=color<<8 | (color &0xff000000)>>24;
791                 vgSetColor(vgttpaint,color);
792                 vgSetPaint((VGPaint) vgttpaint,VG_FILL_PATH);
793                 vgSetPaint((VGPaint) vgttpaint,VG_STROKE_PATH);
794                 cTeletextChar filled;
795                 filled.setInternal(0x187f);
796                 unsigned int glyph_index=loadTTchar(filled);
797                 vgDrawGlyph(vgttfont,glyph_index,VG_FILL_PATH,VG_FALSE);
798
799                 color=Surface::enumTeletextColorToCoulour(ttforegcolour).rgba();
800                 color=color<<8 | (color &0xff000000)>>24;
801                 vgSetColor(vgttpaint,color);
802                 vgSetPaint((VGPaint) vgttpaint,VG_FILL_PATH);
803                 vgSetPaint((VGPaint) vgttpaint,VG_STROKE_PATH);
804                 glyph_index=loadTTchar(tchar);
805                 vgDrawGlyph(vgttfont,glyph_index,VG_FILL_PATH,VG_FALSE);
806
807                 /*      Log::getInstance()->log("OSD", Log::DEBUG, "Draw TTchar %x %x %x %x",glyph_index,ttforegcolour,Surface::enumTeletextColorToCoulour(ttforegcolour).rgba(),
808                                         vgGetColor(vgttpaint));*/
809
810
811                 vgLoadMatrix(save_matrix);
812                 vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
813                 vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_NORMAL);
814                 vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);
815
816         }break;
817         }
818 }
819
820 unsigned int OsdOpenVG::handleTask(OpenVGCommand& command)
821 {
822         switch (command.task){
823         case OVGdestroyImageRef: {
824                 vgDestroyImage((VGImage)command.param1);
825                 return 0;
826         } break;
827         case OVGdestroyPaint: {
828                 Log::getInstance()->log("OSD", Log::DEBUG, "Draw Paint Destroy %d ",command.param1);
829                 vgDestroyPaint((VGPaint)command.param1);
830                 return 0;
831         } break;
832         case OVGcreateImagePalette: {
833                 VGImage input=vgCreateImage(VG_A_8,command.param1, command.param2,
834                                 VG_IMAGE_QUALITY_NONANTIALIASED|
835                                 VG_IMAGE_QUALITY_FASTER|VG_IMAGE_QUALITY_BETTER);
836                 vgImageSubData(input,command.data,command.param1,
837                                                         VG_A_8,0,0,command.param1, command.param2); // upload palettized image data
838                 VGImage handle=vgCreateImage(VG_sRGBA_8888,command.param1, command.param2,
839                                                 VG_IMAGE_QUALITY_NONANTIALIASED|
840                                                 VG_IMAGE_QUALITY_FASTER|VG_IMAGE_QUALITY_BETTER);
841                 VGuint *palette=(VGuint*)malloc(256*sizeof(VGuint));
842                 VGuint *in_palette=(VGuint*)command.data2;
843                 for (int i=0;i<256;i++) {
844                         VGuint color=in_palette[i];
845                         palette[i]=color<<8 | (color &0xff000000)>>24;
846                 }
847
848                 vgLookupSingle(handle,input,palette,VG_ALPHA,VG_FALSE,VG_FALSE);
849                 free(palette);
850                 vgDestroyImage(input);
851
852                 return handle;
853         } break;
854         case OVGcreateMonoBitmap: {
855                 VGImage handle=vgCreateImage(VG_A_1,command.param1, command.param2,
856                                         VG_IMAGE_QUALITY_NONANTIALIASED|
857                                         VG_IMAGE_QUALITY_FASTER|VG_IMAGE_QUALITY_BETTER);
858                 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw create mono  %d %d %x %d",command.param1,command.param2,vgGetError(),handle);
859                 unsigned int buffer_len=(command.param1*command.param2)>>3;
860                 unsigned char * buffer=(unsigned char*)malloc(buffer_len);
861                 unsigned char * r_buffer1=buffer;
862                 const unsigned char * r_buffer2=(const unsigned char *)command.data;
863                 unsigned char *buffer_end=buffer+buffer_len;
864                 while (r_buffer1!=buffer_end) {
865                         unsigned char byte=*r_buffer2;
866                         *r_buffer1=((byte * 0x0802LU & 0x22110LU) | (byte * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
867                         r_buffer1++;r_buffer2++;
868                 }
869
870
871                 vgImageSubData(handle,buffer,command.param1>>3,
872                                         VG_A_1,0,0,command.param1, command.param2);
873                 free(buffer);
874         //      Log::getInstance()->log("OSD", Log::DEBUG, "Draw create mono2  %d %d %x %d",command.param1,command.param2,vgGetError(),handle);
875                 return handle;
876         } break;
877         case OVGcreateImageFile: {
878                 VGImage handle;
879                 try{
880                         Image *imagefile=(Image*)command.data;
881                         Blob imageblob;
882                         imagefile->write(&imageblob,"RGBA");
883
884
885                         handle=vgCreateImage(VG_sXBGR_8888,imagefile->columns(),imagefile->rows(),
886                                         VG_IMAGE_QUALITY_NONANTIALIASED|
887                                         VG_IMAGE_QUALITY_FASTER|VG_IMAGE_QUALITY_BETTER);
888                 //      Log::getInstance()->log("OSD", Log::DEBUG, "Draw create image details  %d %d %x mark1",imagefile->columns(),imagefile->rows(),*(unsigned int*)imageblob.data());
889                         vgImageSubData(handle,imageblob.data(),imagefile->columns()*4,
890                                         VG_sXBGR_8888,0,0,imagefile->columns(),imagefile->rows());
891                 //      Log::getInstance()->log("OSD", Log::DEBUG, "Draw create image details  %d %d %x mark2",imagefile->columns(),imagefile->rows(),*(unsigned int*)imageblob.data());
892                         delete imagefile;
893                 }catch( Exception &error_ )
894                 {
895                         Log::getInstance()->log("OSD", Log::DEBUG, "Libmagick hT: %s",error_.what());
896
897                         return 0;
898                 }
899
900                 //Log::getInstance()->log("OSD", Log::DEBUG, "Draw create file  %d %d %x %d",command.param1,command.param2,vgGetError(),handle);
901                 return handle;
902         } break;
903         case OVGcreateColorRef :{
904                 VGPaint handle;
905                 handle=vgCreatePaint();
906                 vgSetParameteri(handle, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
907                 vgSetColor(handle,command.param1);
908                 VGuint rgba;
909                 rgba = vgGetColor((VGPaint)handle);
910                 Log::getInstance()->log("OSD", Log::DEBUG, "Draw Paint %d %x %x",handle,command.param1,rgba);
911                 return handle;
912         } break;
913         case OVGimageUploadLine: {
914                 vgImageSubData((VGImage)command.param1,command.data,0,VG_sARGB_8888,0,command.param2,command.param3,1);
915                 return 0;
916         } break;
917
918         }
919 }
920
921 bool OsdOpenVG::processTasks()
922 {
923         bool worked=false;
924         taskmutex.Lock();
925         vgmutex.Lock();
926         while (vgcommands.size()>0)
927         {
928                 OpenVGCommand &comm=vgcommands.front();
929                 OpenVGResponse resp;
930                 resp.result=handleTask(comm);
931                 resp.id=comm.id;
932                 if (comm.id) {
933                         vgresponses.push_back(resp);
934                 }
935                 vgcommands.pop_front();
936                 taskmutex.Unlock();
937                 vgmutex.Unlock();
938                 //threadCheckExit();
939                 pthread_mutex_lock(&vgtaskCondMutex);
940                 pthread_cond_signal(&vgtaskCond);
941                 pthread_mutex_unlock(&vgtaskCondMutex);
942                 taskmutex.Lock();
943                 vgmutex.Lock();
944                 worked=true;
945         }
946         taskmutex.Unlock();
947         vgmutex.Unlock();
948
949         return worked;
950 }
951
952 bool OsdOpenVG::haveOpenVGResponse(unsigned int id,unsigned int * resp)
953 {
954         taskmutex.Lock();
955         if (vgresponses.size()>0)
956         {
957                 deque<OpenVGResponse>::iterator itty=vgresponses.begin();
958                 while (itty!=vgresponses.end())
959                 {
960                         if ((*itty).id==id) {
961                                 *resp=(*itty).result;
962                                 taskmutex.Unlock();
963                                 return true;
964                         }
965                         itty++;
966                 }
967         }
968         taskmutex.Unlock();
969         return false;
970 }
971
972
973 unsigned int  OsdOpenVG::putOpenVGCommand(OpenVGCommand& comm,bool wait)
974 {
975         taskmutex.Lock();
976         if (wait){
977                 comm.id=wait_id;
978                 wait_id++;
979         } else {
980                 comm.id=0; // we are not waiting
981         }
982         vgcommands.push_back(comm);
983         taskmutex.Unlock();
984         threadSignal();
985         while (wait) {
986                 unsigned int resp;
987                 if (!haveOpenVGResponse(comm.id,&resp)) {
988                         struct timespec target_time;
989                         clock_gettime(CLOCK_REALTIME,&target_time);
990                         target_time.tv_nsec+=1000000LL*100;
991                         if (target_time.tv_nsec>999999999) {
992                                         target_time.tv_nsec-=1000000000L;
993                                         target_time.tv_sec+=1;
994                         }
995                         pthread_mutex_lock(&vgtaskCondMutex);
996                         pthread_cond_timedwait(&vgtaskCond, &vgtaskCondMutex,&target_time);
997                         pthread_mutex_unlock(&vgtaskCondMutex);
998                 } else {
999                         return resp;
1000                 }
1001         }
1002         return 0;
1003 }
1004
1005 void OsdOpenVG::imageUploadLine(ImageIndex index,unsigned int j,unsigned int width,void *data)
1006 {
1007         vgImageSubData((VGImage)index,data,0,VG_sARGB_8888,0,j,width,1);
1008
1009         struct OpenVGCommand comm;
1010         comm.task=OVGimageUploadLine;
1011         comm.param1=index;
1012         comm.param2=j;
1013         comm.param3=width;
1014         comm.data=data;
1015         putOpenVGCommand(comm,true);
1016 }
1017
1018 void OsdOpenVG::destroyImageRef(ImageIndex index)
1019 {
1020         struct OpenVGCommand comm;
1021         comm.task=OVGdestroyImageRef;
1022         comm.param1=index;
1023         putOpenVGCommand(comm,false);
1024 }
1025
1026 ImageIndex OsdOpenVG::createJpeg(const char* fileName, int *width,int *height)
1027 {
1028         Image* magicimage=NULL;
1029         bool mem=false;
1030         struct OpenVGCommand comm;
1031         comm.task=OVGcreateImageFile;
1032
1033         try{
1034                 // Now figure out, if it is a special case
1035                 if (strcmp(fileName,"/vdr.jpg")==0) {
1036                         magicimage=new Image(Blob(vdr_data,vdr_data_end-vdr_data));
1037                         *height=100; // this is faked so that the system does use the old coordinate system
1038                         *width=ceil(190.f*aspect_correction);
1039                         Log::getInstance()->log("OSD", Log::DEBUG, "LoadIm vdr.jpg");
1040                 } else if (strcmp(fileName,"/wallpaperPAL.jpg")==0) {
1041                         magicimage=new Image(Blob(wallpaper_data,wallpaper_data_end-wallpaper_data));
1042                         *width=720; // this is faked so that the system does use the old coordinate system
1043                         *height=576;
1044                         Log::getInstance()->log("OSD", Log::DEBUG, "LoadIm wallpaperPAL.jpg");
1045                 } else {
1046                         magicimage=new Image();
1047                         magicimage->read(fileName);
1048                         Log::getInstance()->log("OSD", Log::DEBUG, "LoadIm file: %s",fileName);
1049                         *width=ceil(magicimage->baseColumns()*aspect_correction); // this is faked so that the system does use the old coordinate system
1050                         *height=magicimage->baseRows();
1051                 }
1052
1053         }catch( Exception &error_ )
1054         {
1055                 Log::getInstance()->log("OSD", Log::DEBUG, "Libmagick: %s",error_.what());
1056
1057                 return 0;
1058         }
1059         comm.data=magicimage;
1060         return putOpenVGCommand(comm,true);
1061 }
1062
1063 ImageIndex OsdOpenVG::createMonoBitmap(void *base,int width,int height)
1064 {
1065         struct OpenVGCommand comm;
1066         comm.task=OVGcreateMonoBitmap;
1067         comm.param1=width;
1068         comm.param2=height;
1069         comm.data=base;
1070         return putOpenVGCommand(comm,true);
1071 }
1072
1073 ImageIndex OsdOpenVG::createImagePalette(int width,int height,const unsigned char *image_data,const unsigned int*palette_data)
1074 {
1075     struct OpenVGCommand comm;
1076     comm.task=OVGcreateImagePalette;
1077     comm.param1=width;
1078     comm.param2=height;
1079     comm.data=image_data;
1080     comm.data2=palette_data;
1081     return putOpenVGCommand(comm,true);
1082 }
1083
1084 void OsdOpenVG::destroyStyleRef(unsigned int index)
1085 {
1086         struct OpenVGCommand comm;
1087         comm.task=OVGdestroyPaint;
1088         comm.param1=index;
1089         putOpenVGCommand(comm,false);
1090 }
1091
1092 unsigned int OsdOpenVG::createStyleRef(const DrawStyle &c)
1093 {
1094         unsigned int col=c.rgba();
1095         struct OpenVGCommand comm;
1096         comm.task=OVGcreateColorRef;
1097         comm.param1=col<<8 | (col &0xff000000)>>24;
1098         comm.data=&c;
1099         return putOpenVGCommand(comm,true);
1100 }
1101
1102 unsigned int OsdOpenVG::createColorRef(const Colour &c)
1103 {
1104         unsigned int col=c.rgba();
1105         struct OpenVGCommand comm;
1106         comm.task=OVGcreateColorRef;
1107         comm.param1=col<<8 | (col &0xff000000)>>24;
1108         comm.data=&c;
1109         return putOpenVGCommand(comm,true);
1110 }
1111
1112