]> git.vomp.tv Git - vompclient.git/blob - osdwin.cc
Fix delete
[vompclient.git] / osdwin.cc
1 /*\r
2     Copyright 2004-2005 Chris Tallon\r
3 \r
4     This file is part of VOMP.\r
5 \r
6     VOMP is free software; you can redistribute it and/or modify\r
7     it under the terms of the GNU General Public License as published by\r
8     the Free Software Foundation; either version 2 of the License, or\r
9     (at your option) any later version.\r
10 \r
11     VOMP is distributed in the hope that it will be useful,\r
12     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14     GNU General Public License for more details.\r
15 \r
16     You should have received a copy of the GNU General Public License\r
17     along with VOMP; if not, write to the Free Software\r
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 */\r
20 \r
21 \r
22 #include "osdwin.h"\r
23 #include "mtd.h"\r
24 #include "video.h"\r
25 #include "surfacewin.h"\r
26 \r
27 #include "dsallocator.h"\r
28 \r
29 \r
30 //This is stuff for rendering the OSD\r
31 \r
32 \r
33 OsdWin::OsdWin()\r
34 {\r
35   d3d=NULL;\r
36   d3ddevice=NULL;\r
37   d3dvb=NULL;\r
38   d3drtsurf=NULL;\r
39   external_driving=false;\r
40   dsallocator=NULL;\r
41   event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL);\r
42   d3dmutex = CreateMutex(NULL,FALSE,NULL);\r
43   \r
44 }\r
45 \r
46 OsdWin::~OsdWin()\r
47 {\r
48   if (initted) shutdown();\r
49   CloseHandle(event);\r
50   CloseHandle(d3dmutex);\r
51 }\r
52 \r
53 int OsdWin::getFD()\r
54 {\r
55   if (!initted) return 0;\r
56   return fdOsd;\r
57 }\r
58 \r
59 int OsdWin::init(void* device)\r
60 {\r
61   if (initted) return 0;\r
62    Video* video = Video::getInstance();\r
63   //First Create Direct 3D Object\r
64   d3d=Direct3DCreate9(D3D_SDK_VERSION);\r
65   if (!d3d) \r
66   {\r
67     Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 object!");\r
68     return 0;\r
69   }\r
70   // then create the Device\r
71   D3DPRESENT_PARAMETERS d3dparas;\r
72   ZeroMemory(&d3dparas,sizeof(d3dparas));\r
73   d3dparas.BackBufferWidth=video->getScreenWidth();\r
74   d3dparas.BackBufferHeight=video->getScreenHeight();\r
75   d3dparas.Windowed=TRUE;\r
76   d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;\r
77   if (d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,*((HWND*) device),\r
78           D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dparas,&d3ddevice)!=D3D_OK) {\r
79            Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 device!");\r
80        return 0;\r
81   }\r
82   d3ddevice->GetRenderTarget(0,&d3drtsurf);\r
83 \r
84   if (!InitVertexBuffer()) {\r
85            Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 vertex buf!");\r
86                   return 0;\r
87   }\r
88 \r
89   //Now we will create the Screen\r
90   screen = new SurfaceWin(Surface::SCREEN);\r
91   SetEvent(event);//Now all devices are ready\r
92   screen->create(video->getScreenWidth(), video->getScreenHeight());\r
93   screen->display();\r
94   initted = 1; // must set this here or create surface won't work\r
95   \r
96   return 1;\r
97 }\r
98 \r
99 \r
100 int OsdWin::InitVertexBuffer() {\r
101   Video* video = Video::getInstance();\r
102   FLOAT texx=((float)video->getScreenWidth())/1024.f;\r
103   FLOAT texy=((float)video->getScreenHeight())/1024.f;\r
104   D3DCOLOR osdcolor=D3DCOLOR_RGBA(255,255,255,255);\r
105   osdvertices[0].c=osdcolor;\r
106   osdvertices[0].x=0.f-0.5f;\r
107   osdvertices[0].y=0.f-0.5f;\r
108   osdvertices[0].z=0.5f;\r
109   osdvertices[0].rhw=1.f;\r
110   osdvertices[0].u=0.f;\r
111   osdvertices[0].v=0.f;\r
112   osdvertices[1].c=osdcolor;\r
113   osdvertices[1].x=((float)video->getScreenWidth())-0.5f;-0.5f;\r
114   osdvertices[1].y=0.f-0.5f;\r
115   osdvertices[1].z=0.5f;\r
116   osdvertices[1].u=texx;\r
117   osdvertices[1].v=0.f;\r
118   osdvertices[1].rhw=1.f;\r
119   osdvertices[2].c=osdcolor;\r
120   osdvertices[2].x=((float)video->getScreenWidth())-0.5f;\r
121   osdvertices[2].y=((float)video->getScreenHeight())-0.5f;\r
122   osdvertices[2].z=0.5f;\r
123   osdvertices[2].rhw=1.f;\r
124   osdvertices[2].u=texx;\r
125   osdvertices[2].v=texy;\r
126   osdvertices[3].c=osdcolor;\r
127   osdvertices[3].x=0.f-0.5f;\r
128   osdvertices[3].y=((float)video->getScreenHeight())-0.5f;\r
129   osdvertices[3].z=0;\r
130   osdvertices[3].rhw=1.f;\r
131   osdvertices[3].u=0.f;\r
132   osdvertices[3].v=texy;\r
133   if (d3dvb) {\r
134           d3dvb->Release();\r
135           d3dvb=NULL;\r
136   }\r
137   if (d3ddevice->CreateVertexBuffer(4*sizeof(OSDVERTEX),0,D3DFVF_OSDVERTEX,D3DPOOL_MANAGED,\r
138           &d3dvb,NULL)!=D3D_OK) {\r
139           return 0;\r
140   }\r
141   void *pvertex=NULL;\r
142   if (d3dvb->Lock(0,sizeof(osdvertices),&pvertex,0)!=D3D_OK) {\r
143           return 0;\r
144   }\r
145   memcpy(pvertex,osdvertices,sizeof(osdvertices));\r
146   d3dvb->Unlock();\r
147   return 1;\r
148 }\r
149 \r
150 int OsdWin::shutdown()\r
151 {\r
152   if (!initted) return 0;\r
153   initted = 0;\r
154   d3drtsurf->Release();\r
155   d3ddevice->Release();\r
156   d3d->Release();\r
157 \r
158   return 1;\r
159 }\r
160 \r
161 void OsdWin::screenShot(char* fileName)\r
162 {\r
163   screen->screenShot(fileName);\r
164 }\r
165 \r
166 // This function is called from the WinMain function in order to get Screen updates\r
167 void OsdWin::Render()\r
168 {\r
169         if (!initted) return ;\r
170         if (external_driving) {\r
171                 Sleep(5); //Sleep for 5 ms, in order to avoid blocking the other threads\r
172         } else {\r
173                 InternalRendering(NULL);\r
174         }\r
175 }\r
176 \r
177 void OsdWin::RenderDS(LPDIRECT3DSURFACE9 present){\r
178         if (!initted) return;\r
179         if (external_driving) {\r
180                 InternalRendering(present);\r
181         }\r
182 }\r
183 \r
184 \r
185 void OsdWin::InternalRendering(LPDIRECT3DSURFACE9 present){\r
186         WaitForSingleObject(event,INFINITE);\r
187         BeginPainting();\r
188         if (external_driving) {\r
189                 //Copy video to Backbuffer\r
190                 if (present!=NULL) {\r
191                         d3ddevice->StretchRect(present,NULL,d3drtsurf  ,NULL,D3DTEXF_LINEAR);\r
192 \r
193                 }\r
194         } else {\r
195                 //Clear Background\r
196                 d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,255),1.0f,0);\r
197         }\r
198         //Drawing the OSD\r
199         if (d3ddevice->BeginScene()==D3D_OK) {\r
200                 d3ddevice->SetStreamSource(0,d3dvb,0,sizeof(OSDVERTEX));\r
201                 d3ddevice->SetFVF(D3DFVF_OSDVERTEX);\r
202                 d3ddevice->SetTexture(0,((SurfaceWin*)screen)->getD3dtexture());\r
203                 //d3ddevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);\r
204                 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP,D3DTOP_MODULATE);\r
205                 d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);\r
206                 d3ddevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);\r
207                 d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);\r
208                 d3ddevice->SetRenderState(D3DRS_LIGHTING,FALSE);\r
209 \r
210 \r
211                 d3ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN,0,2);\r
212                 d3ddevice->EndScene();\r
213                 //Show it to the user!\r
214                 if (d3ddevice->Present(NULL,NULL,NULL,NULL)==D3DERR_DEVICELOST){\r
215                         EndPainting();\r
216                         DoLost();\r
217                 }\r
218                 EndPainting();\r
219         }\r
220         if (!external_driving) {\r
221                 Sleep(4);//The User can wait for 4 milliseconds to see his changes\r
222         }\r
223 }\r
224 \r
225 void OsdWin::DoLost(){\r
226         Log::getInstance()->log("OSD", Log::WARN, "Direct3D Device Lost! Reobtaining...");\r
227         ResetEvent(event);\r
228         if (external_driving && dsallocator!=NULL) {\r
229                 dsallocator->LostDevice(); //Propagate the information through DS\r
230         }\r
231         //First we free up all resources\r
232         Video* video = Video::getInstance();\r
233         ((SurfaceWin*)screen)->ReleaseSurface();\r
234         d3drtsurf->Release();\r
235         d3dvb->Release();\r
236         d3dvb=NULL;\r
237         D3DPRESENT_PARAMETERS d3dparas;\r
238         ZeroMemory(&d3dparas,sizeof(d3dparas));\r
239         d3dparas.BackBufferWidth=video->getScreenWidth();\r
240         d3dparas.BackBufferHeight=video->getScreenHeight();\r
241         d3dparas.Windowed=TRUE;\r
242         d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;\r
243         if (d3ddevice->Reset(&d3dparas)!=D3D_OK){\r
244                 return;\r
245         }\r
246         screen->create(video->getScreenWidth(), video->getScreenHeight());\r
247         screen->display();\r
248         d3ddevice->GetRenderTarget(0,&d3drtsurf);\r
249         InitVertexBuffer();\r
250         //Redraw Views, Chris could you add a member function to viewman, so that\r
251         // I can cause it to completely redraw the Views?\r
252         // Otherwise the OSD would be distorted after Device Lost\r
253         \r
254         SetEvent(event);\r
255 \r
256 }\r
257 LPDIRECT3DDEVICE9 OsdWin::getD3dDev() {\r
258         WaitForSingleObject(event,INFINITE);//We will only return if we are initted\r
259         return d3ddevice;\r
260 }\r
261 \r
262 LPDIRECT3D9 OsdWin::getD3d() {\r
263         WaitForSingleObject(event,INFINITE);//We will only return if we are initted\r
264         return d3d;\r
265 }\r
266 \r
267 void OsdWin::BeginPainting() {//We synchronize calls to d3d between different threads\r
268         WaitForSingleObject(d3dmutex,INFINITE);\r
269 }\r
270 \r
271 void OsdWin::EndPainting() {\r
272         ReleaseMutex(d3dmutex);\r
273 }\r
274 \r
275 void OsdWin::setExternalDriving(DsAllocator* dsall) {\r
276         if (dsall==NULL) {\r
277                 external_driving=false;\r
278                 dsallocator=NULL;\r
279                 return;\r
280         }\r
281         WaitForSingleObject(event,INFINITE);//We will only return if we are initted\r
282         dsallocator=dsall;\r
283         external_driving=true;\r
284 }\r