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