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