]> git.vomp.tv Git - vompclient.git/blob - osdwin.cc
Remove windows debugging code
[vompclient.git] / osdwin.cc
1 /*
2     Copyright 2004-2005 Chris Tallon
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 "osdwin.h"
23 #include "mtd.h"
24 #include "videowin.h"
25 #include "surfacewin.h"
26
27 #include "dsallocator.h"
28 #include "message.h"
29 #include "command.h"
30
31 #define  BACKBUFFER_WIDTH 1920
32 #define  BACKBUFFER_HEIGHT 1080
33
34
35
36 typedef HRESULT (__stdcall *FCT_DXVA2CreateDirect3DDeviceManager9)(UINT* pResetToken, IDirect3DDeviceManager9** ppDeviceManager);
37 typedef HRESULT (__stdcall *FCT_MFCreateVideoSampleFromSurface)(IUnknown* pUnkSurface, IMFSample** ppSample);
38
39 FCT_DXVA2CreateDirect3DDeviceManager9 ptrDXVA2CreateDirect3DDeviceManager9=NULL;
40 FCT_MFCreateVideoSampleFromSurface ptrMFCreateVideoSampleFromSurface=NULL;
41
42 //This is stuff for rendering the OSD
43
44
45 OsdWin::OsdWin()
46 {
47   d3d=NULL;
48   d3ddevice=NULL;
49   d3drtsurf=NULL;
50   swappy=NULL;
51   swapsurf=NULL;
52   evrstate=EVR_pres_off;
53   window=NULL;
54
55   external_driving=false;
56   dsallocator=NULL;
57   filter_type=D3DTEXF_FORCE_DWORD;
58   lastrendertime=timeGetTime();
59   event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL);
60   d3dmutex = CreateMutex(NULL,FALSE,NULL);
61   /*EVR stuff*/
62   dxvadevicehandle=NULL;
63   evrsupported=true;
64   HMODULE hlib=NULL;
65   hlib=LoadLibrary("dxva2.dll");
66   if (!hlib) {
67           evrsupported=false;
68           return;
69   }
70   ptrDXVA2CreateDirect3DDeviceManager9=(FCT_DXVA2CreateDirect3DDeviceManager9)GetProcAddress(hlib, "DXVA2CreateDirect3DDeviceManager9");
71   if (!ptrDXVA2CreateDirect3DDeviceManager9){
72           evrsupported=false;
73           return;
74   }
75
76   hlib=LoadLibrary("evr.dll");
77   if (!hlib) {
78           evrsupported=false;
79           return;
80   }
81  
82   ptrMFCreateVideoSampleFromSurface = (FCT_MFCreateVideoSampleFromSurface)GetProcAddress(hlib,"MFCreateVideoSampleFromSurface");
83   if (!ptrMFCreateVideoSampleFromSurface){
84           evrsupported=false;
85           return;
86   }
87   
88 }
89
90 OsdWin::~OsdWin()
91 {
92
93   if (initted) 
94   {
95           threadStop();
96                 shutdown();
97   }
98   CloseHandle(event);
99   CloseHandle(d3dmutex);
100 }
101
102 int OsdWin::getFD()
103 {
104   if (!initted) return 0;
105   return fdOsd;
106 }
107
108 Surface * OsdWin::createNewSurface(){
109         return (Surface*)new SurfaceWin();
110 }
111
112 int OsdWin::init(void* device)
113 {
114   if (initted) return 0;
115    Video* video = Video::getInstance();
116    window=*((HWND*)device);
117   //First Create Direct 3D Object
118   d3d=Direct3DCreate9(D3D_SDK_VERSION);
119   if (!d3d) 
120   {
121     Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 object!");
122     return 0;
123   }
124   // then create the Device
125   D3DPRESENT_PARAMETERS d3dparas;
126   ZeroMemory(&d3dparas,sizeof(d3dparas));
127   d3dparas.BackBufferWidth=BACKBUFFER_WIDTH;
128   d3dparas.BackBufferHeight=BACKBUFFER_HEIGHT;
129   d3dparas.Windowed=TRUE;
130   d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;
131   if (d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,*((HWND*) device),
132           D3DCREATE_SOFTWARE_VERTEXPROCESSING |D3DCREATE_MULTITHREADED,&d3dparas,&d3ddevice)!=D3D_OK) {
133            Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 device!");
134        return 0;
135   }
136   d3ddevice->GetRenderTarget(0,&d3drtsurf);
137
138   /*
139   if (!InitVertexBuffer()) {
140            Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 vertex buf!");
141                   return 0;
142   }*/
143   /* We have to determine which kind of filtering is supported*/
144   D3DCAPS9 caps;
145   d3ddevice->GetDeviceCaps(&caps);
146   if ( ((caps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFLINEAR)!=0)
147           && ((caps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)!=0)) {
148           if (filter_type==D3DTEXF_FORCE_DWORD) {
149                         filter_type=D3DTEXF_LINEAR;
150           }
151   } else {
152       if (filter_type==D3DTEXF_LINEAR)
153       {
154           filter_type=D3DTEXF_POINT;
155       }
156   }
157   
158   if ( ((caps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFPOINT)!=0)
159           && ((caps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFPOINT)!=0)) {
160        if (filter_type==D3DTEXF_FORCE_DWORD) 
161        {
162                   filter_type=D3DTEXF_POINT;
163    }
164    } else {
165        if (filter_type==D3DTEXF_POINT) {
166            filter_type=D3DTEXF_NONE;
167    }
168    }
169    if (filter_type==D3DTEXF_FORCE_DWORD) {
170        filter_type=D3DTEXF_NONE;
171    }
172
173    if (evrsupported)
174    {
175            if (ptrDXVA2CreateDirect3DDeviceManager9(&dxvatoken,&d3ddevman)!=S_OK) evrsupported=false;
176            else {
177                    d3ddevman->ResetDevice(d3ddevice,dxvatoken);
178            }
179    }
180
181    GdiplusStartup(&gdiptoken, &gdipstartup, NULL);
182
183
184   //Now we will create the Screen
185   screen = new SurfaceWin(Surface::SCREEN);
186   SetEvent(event);//Now all devices are ready
187   screen->create(video->getScreenWidth(), video->getScreenHeight());
188   screen->display();
189   initted = 1; // must set this here or create surface won't work
190   threadStart(); 
191
192   return 1;
193 }
194
195 void OsdWin::LockDevice()
196 {
197         if (!evrsupported) return;
198         if (!dxvadevicehandle) 
199         {
200                 d3ddevman->OpenDeviceHandle(&dxvadevicehandle);
201         }
202         IDirect3DDevice9 *temp;
203         d3ddevman->LockDevice(dxvadevicehandle,&temp,TRUE);
204
205 }
206
207 void OsdWin::UnlockDevice()
208 {
209         if (!evrsupported) return;
210         if (!initted) return;
211         d3ddevman->UnlockDevice(dxvadevicehandle,TRUE);
212         if (dxvadevicehandle) 
213         {
214                 d3ddevman->CloseDeviceHandle(dxvadevicehandle);
215                 dxvadevicehandle=NULL;
216         }
217
218 }
219
220 DWORD OsdWin::getFilterCaps()
221 {
222     if (!initted) return NULL;
223     D3DCAPS9 caps;
224     d3ddevice->GetDeviceCaps(&caps);
225     return caps.StretchRectFilterCaps;
226 }
227         
228 LPDIRECT3DVERTEXBUFFER9  OsdWin::InitVertexBuffer(DWORD width, DWORD height)
229 {
230   LPDIRECT3DVERTEXBUFFER9 ret =NULL;
231   Video* video=Video::getInstance();
232   FLOAT texx=((float)video->getScreenWidth())/1024.f;
233   FLOAT texy=((float)video->getScreenHeight())/1024.f;
234   D3DCOLOR osdcolor=D3DCOLOR_RGBA(255,255,255,255);
235   osdvertices[0].c=osdcolor;
236   osdvertices[0].x=0.f-0.5f;
237   osdvertices[0].y=0.f-0.5f;
238   osdvertices[0].z=0.5f;
239   osdvertices[0].rhw=1.f;
240   osdvertices[0].u=0.f;
241   osdvertices[0].v=0.f;
242   osdvertices[1].c=osdcolor;
243   osdvertices[1].x=((float)width)-0.5f;
244   osdvertices[1].y=0.f-0.5f;
245   osdvertices[1].z=0.5f;
246   osdvertices[1].u=texx;
247   osdvertices[1].v=0.f;
248   osdvertices[1].rhw=1.f;
249   osdvertices[2].c=osdcolor;
250   osdvertices[2].x=((float)width)-0.5f;
251   osdvertices[2].y=((float)height)-0.5f;
252   osdvertices[2].z=0.5f;
253   osdvertices[2].rhw=1.f;
254   osdvertices[2].u=texx;
255   osdvertices[2].v=texy;
256   osdvertices[3].c=osdcolor;
257   osdvertices[3].x=0.f-0.5f;
258   osdvertices[3].y=((float)height)-0.5f;
259   osdvertices[3].z=0.5f;
260   osdvertices[3].rhw=1.f;
261   osdvertices[3].u=0.f;
262   osdvertices[3].v=texy;
263   
264   if (d3ddevice->CreateVertexBuffer(4*sizeof(OSDVERTEX),0,D3DFVF_OSDVERTEX,D3DPOOL_MANAGED,
265           &ret,NULL)!=D3D_OK) {
266           return NULL;
267   }
268   void *pvertex=NULL;
269   if (ret->Lock(0,sizeof(osdvertices),&pvertex,0)!=D3D_OK) {
270           return NULL;
271   }
272   memcpy(pvertex,osdvertices,sizeof(osdvertices));
273   ret->Unlock();
274   return ret;
275 }
276
277 int OsdWin::shutdown()
278 {
279   if (!initted) return 0;
280   initted = 0;
281   evrsupported=0;
282   if (d3ddevman) d3ddevman->Release();
283   d3drtsurf->Release();
284   d3ddevice->Release();
285   d3d->Release();
286   if (swapsurf) swapsurf->Release();
287   if (swappy) swappy->Release();
288   Gdiplus::GdiplusShutdown(gdiptoken);
289
290   return 1;
291 }
292
293 void OsdWin::screenShot(const char* fileName)
294 {
295   screen->screenShot(fileName);
296 }
297
298 void OsdWin::threadMethod()
299 {
300         while (true)
301         {
302                 DWORD waittime=10;
303                 if (initted){
304                         if (evrstate==EVR_pres_off || evrstate==EVR_pres_pause) 
305                         {
306                                 Render();
307                         } else if (evrstate==EVR_pres_started)
308                         {
309                                 LPDIRECT3DSURFACE9 surf;
310                                 if (dsallocator) dsallocator->GetNextSurface(&surf,&waittime);
311                                 if (surf==NULL)
312                                 {
313                                         Render();
314                                 }
315                                 else
316                                 {
317                                         RenderDS(surf);
318                                         surf->Release();
319                                         if (dsallocator) dsallocator->DiscardSurfaceandgetWait(&waittime);
320                                 }
321                         }
322                 }
323                 threadCheckExit();
324                 if (waittime!=0) Sleep(min(10,waittime));
325                 //Sleep(1);
326         }
327 }
328
329
330 void OsdWin::threadPostStopCleanup()
331 {
332         //Doing nothing
333         //goo;
334 }
335
336
337 // This function is called from the WinMain function in order to get Screen updates
338 void OsdWin::Render()
339 {
340         if (!initted) return ;
341         if (external_driving) {
342         DWORD time1=timeGetTime(); //Updates the Menue
343                 if ((time1-lastrendertime)>200) {//5 fps for OSD updates are enough, avoids tearing
344                         InternalRendering(NULL);
345                         lastrendertime=timeGetTime();
346         } else {
347                    //Sleep(5); //Sleep for 5 ms, in order to avoid blocking the other threads
348         }
349         } else {
350                 DWORD time1=timeGetTime();
351                 if ((time1-lastrendertime)>50) {//10 fps for OSD updates are enough, avoids tearing
352                         InternalRendering(NULL);
353                         lastrendertime=timeGetTime();
354                 } else {
355                         //Sleep(5);
356                 
357                 }
358                 
359         }
360 }
361
362 void OsdWin::RenderDS(LPDIRECT3DSURFACE9 present){
363         if (!initted) return; 
364         if (external_driving) {
365                 InternalRendering(present);
366         lastrendertime=timeGetTime();
367         }
368 }
369
370
371 void OsdWin::InternalRendering(LPDIRECT3DSURFACE9 present){
372     BeginPainting();
373     HRESULT losty=d3ddevice->TestCooperativeLevel();
374     if (losty==D3DERR_DEVICELOST) {
375         //Sleep(10);
376                 EndPainting();
377         return; //Device Lost
378     }
379     if (losty==D3DERR_DEVICENOTRESET){
380            EndPainting();
381        DoLost();
382        return;
383     }
384         WaitForSingleObject(event,INFINITE);
385         
386    
387         
388     
389     LPDIRECT3DSURFACE9 targetsurf;
390         if (swappy)
391         {
392                 targetsurf=swapsurf;
393                 d3ddevice->SetRenderTarget(0,swapsurf);//Stupid VMR manipulates the render target
394         } 
395         else
396         {
397                 targetsurf=d3drtsurf;
398                 d3ddevice->SetRenderTarget(0,d3drtsurf);//Stupid VMR manipulates the render target
399         }
400         D3DSURFACE_DESC targetdesc;
401         targetsurf->GetDesc(&targetdesc);
402
403         if (external_driving) {
404                 //Copy video to Backbuffer
405                 if (present!=NULL ) {
406                         VideoWin* video =(VideoWin*) Video::getInstance();
407                         /*calculating destination rect */
408                         RECT destrect={0,0,/*video->getScreenWidth()*/ targetdesc.Width,
409                                 /*video->getScreenHeight()*/targetdesc.Height};
410                         const VideoDisplay &vd=video->getVideoDisplay();
411                         int addx, addy;
412                         addx = addy = 0;
413
414                         switch (vd.mode) {
415                         case Eighth:
416                                 destrect.right=destrect.right/2;
417                                 destrect.bottom=destrect.bottom/2;
418                         case Quarter:
419                                 destrect.right=destrect.right/2;
420                                 destrect.bottom=destrect.bottom/2;
421                         break;
422                         case Window:
423                                 float imageaspect = 720.f / 576.f;
424                                 float boxaspect = ((float)vd.width) / ((float)vd.height) ;
425                                 float videoaspect = ((float)targetdesc.Width) / ((float)targetdesc.Height);
426                                 if (imageaspect > boxaspect) {
427                                         destrect.right = (int)(((float)destrect.right) * ((float)vd.width) / 720.f);
428                                         destrect.bottom = (int)(((float)destrect.right)/videoaspect);
429                                         addy += (((float)vd.height) - ((float)vd.width) / imageaspect)*0.5f / 576.f 
430                                                 *((float)targetdesc.Height);
431                                 }
432                                 else {
433                                         destrect.bottom = (int)(((float)destrect.bottom) * ((float)vd.height) / 576.f);
434                                         destrect.right = (int)(((float)destrect.bottom)*videoaspect);
435                                         addx += (((float)vd.width) - ((float)vd.height) * imageaspect)*0.5f / 720.f
436                                                 *((float)targetdesc.Width);
437                                 }
438                                 
439                                 
440                         break;
441                         };
442                         switch (vd.mode) {
443                         case Quarter:
444                         case Eighth:
445                         case Window:
446                                 destrect.left = (int)(((float)vd.x*targetdesc.Width) / 720.f)+addx;
447                                 destrect.top = (int)(((float)vd.y*targetdesc.Height) / 576.f)+addy;
448                                 destrect.right += destrect.left;
449                                 destrect.bottom += destrect.top;
450                         break;
451                         }
452                         d3ddevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
453                         D3DSURFACE_DESC surf_desc;
454                         present->GetDesc(&surf_desc);//for chop sides
455                         RECT sourcerect= {0,0,surf_desc.Width,surf_desc.Height};
456                         if (video->getPseudoTVsize()==Video::ASPECT4X3 
457                                 && video->getMode()==Video::NORMAL 
458                                 && video->getAspectRatio()==Video::ASPECT16X9) {
459                                         unsigned int correction=((double) (surf_desc.Width))*4.*9./3./16.;
460                                         sourcerect.left=(surf_desc.Width-correction)/2;
461                                         sourcerect.right=sourcerect.left+correction;
462                         }
463                         d3ddevice->StretchRect(present,&sourcerect,targetsurf ,&destrect,filter_type);
464
465                 }
466         } else {
467                 VideoWin* video =(VideoWin*) Video::getInstance();
468                 //Clear Background
469                 if (!video->isVideoOn()) d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);
470         }
471         LPDIRECT3DVERTEXBUFFER9 vb=NULL;
472         vb=InitVertexBuffer(targetdesc.Width,targetdesc.Height);
473
474         //Drawing the OSD
475         if (d3ddevice->BeginScene()==D3D_OK) {
476                 d3ddevice->SetStreamSource(0,vb,0,sizeof(OSDVERTEX));
477                 d3ddevice->SetFVF(D3DFVF_OSDVERTEX);
478                 d3ddevice->SetTexture(0,((SurfaceWin*)screen)->getD3dtexture());
479                 //d3ddevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
480                 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP,D3DTOP_MODULATE);
481
482         d3ddevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
483         d3ddevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
484
485
486                 d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
487                 d3ddevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
488                 d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
489                 d3ddevice->SetRenderState(D3DRS_LIGHTING,FALSE);
490
491
492                 d3ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN,0,2);
493                 d3ddevice->EndScene();
494                 //Show it to the user!
495         HRESULT hres;
496                 if (swappy)
497                 {
498                         if (hres=swappy->Present(NULL,NULL,NULL,NULL,0)==D3DERR_DEVICELOST){
499                                 //EndPainting();
500                                 if (!external_driving) DoLost();
501                         }
502                 } 
503                 else
504                 {
505                         if (hres=d3ddevice->Present(NULL,NULL,NULL,NULL)==D3DERR_DEVICELOST){
506                                 //EndPainting();
507                                 if (!external_driving) DoLost();
508                         }
509                 }
510                 
511         }
512         
513         vb->Release();
514         EndPainting();
515
516         
517 //      if (!external_driving) {
518 //              Sleep(4);//The User can wait for 4 milliseconds to see his changes
519 //      }
520 }
521
522 bool OsdWin::DoLost(){
523         Log::getInstance()->log("OSD", Log::WARN, "Direct3D Device Lost! Reobtaining...");
524         ResetEvent(event);
525         if (external_driving && dsallocator!=NULL) {
526                 dsallocator->LostDevice(d3ddevice,d3d); //Propagate the information through DS
527         }
528         //First we free up all resources
529         Video* video = Video::getInstance();
530         ((SurfaceWin*)screen)->ReleaseSurface();
531         if (d3drtsurf) d3drtsurf->Release();
532     d3drtsurf=NULL;
533         D3DPRESENT_PARAMETERS d3dparas;
534         ZeroMemory(&d3dparas,sizeof(d3dparas));
535         d3dparas.BackBufferWidth=BACKBUFFER_WIDTH;
536         d3dparas.BackBufferHeight=BACKBUFFER_HEIGHT;
537         d3dparas.Windowed=TRUE;
538         d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;
539
540         if (swapsurf) {swapsurf->Release();swapsurf=NULL;};
541         if (swappy) {swappy->Release();swappy=NULL;};
542
543         if (d3ddevice->Reset(&d3dparas)!=D3D_OK){
544                 return false;
545         }
546     d3ddevice->GetRenderTarget(0,&d3drtsurf);
547         if (d3ddevman) d3ddevman->ResetDevice(d3ddevice,dxvatoken);
548         //InitVertexBuffer();
549     //Redraw Views, Chris could you add a member function to BoxStack, so that
550         // I can cause it to completely redraw the Views?
551         // Otherwise the OSD would be distorted after Device Lost
552         // FIXME
553         
554         SetEvent(event);
555
556
557         screen->create(video->getScreenWidth(), video->getScreenHeight());
558         screen->display();
559         
560         return true;
561
562 }
563 LPDIRECT3DDEVICE9 OsdWin::getD3dDev() {
564         WaitForSingleObject(event,INFINITE);//We will only return if we are initted
565         return d3ddevice;
566 }
567
568 LPDIRECT3D9 OsdWin::getD3d() {
569         WaitForSingleObject(event,INFINITE);//We will only return if we are initted
570         return d3d;
571 }
572
573 void OsdWin::BeginPainting() {//We synchronize calls to d3d between different threads
574         WaitForSingleObject(d3dmutex,INFINITE);
575         LockDevice();
576 }
577
578 void OsdWin::EndPainting() {
579         UnlockDevice();
580         ReleaseMutex(d3dmutex);
581 }
582
583 void OsdWin::setExternalDriving(DsAllocator* dsall,DWORD width, DWORD height) {
584         
585         if (swappy)
586         {
587                 BeginPainting();
588                 d3ddevice->StretchRect(swapsurf,NULL,d3drtsurf,NULL,filter_type);
589                 LPDIRECT3DSWAPCHAIN9 temp=swappy;
590                 LPDIRECT3DSURFACE9 tempsurf=swapsurf;
591                 swappy=NULL;
592                 swapsurf=NULL;
593                 EndPainting();
594                 tempsurf->Release();
595                 temp->Release();
596         }
597
598         if (dsall==NULL) {
599                 external_driving=false;
600                 dsallocator=NULL;       
601                 return;
602         }
603         WaitForSingleObject(event,INFINITE);//We will only return if we are initted
604         BeginPainting();
605
606         if (width>BACKBUFFER_WIDTH || height>BACKBUFFER_HEIGHT) 
607         {
608                 D3DPRESENT_PARAMETERS d3dparas;
609                 ZeroMemory(&d3dparas,sizeof(d3dparas));
610                 d3dparas.BackBufferWidth=width;
611                 d3dparas.BackBufferHeight=height;
612                 d3dparas.Windowed=TRUE;
613                 d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;
614                 if (d3ddevice->CreateAdditionalSwapChain(&d3dparas,&swappy)!=D3D_OK){
615                         Log::getInstance()->log("OSD", Log::WARN, "Could not create Swap Chain!");
616                         //return 0;
617                 } else {
618                         swappy->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&swapsurf);
619                 }
620         Log::getInstance()->log("OSD", Log::INFO, "Create Additional Swap Chain %d %d!",width,height);
621         }
622
623         dsallocator=dsall;
624         external_driving=true;
625         
626         EndPainting();
627 }
628
629 void OsdWin::Blank() {
630         WaitForSingleObject(event,INFINITE);
631         BeginPainting();
632         d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);
633         EndPainting();
634 }