]> git.vomp.tv Git - vompclient-marten.git/blob - osdwin.cc
Sync changes in demuxer
[vompclient-marten.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "osdwin.h"
22 #include "mtd.h"
23 #include "video.h"
24 #include "surfacewin.h"
25
26 //This is stuff for rendering the OSD
27
28
29 OsdWin::OsdWin()
30 {
31   d3d=NULL;
32   d3ddevice=NULL;
33   d3dvb=NULL;
34   external_driving=false;
35   event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL);
36   d3dmutex = CreateMutex(NULL,FALSE,NULL);
37
38 }
39
40 OsdWin::~OsdWin()
41 {
42   if (initted) shutdown();
43   CloseHandle(event);
44   CloseHandle(d3dmutex);
45 }
46
47 int OsdWin::getFD()
48 {
49   if (!initted) return 0;
50   return fdOsd;
51 }
52
53 int OsdWin::init(void* device)
54 {
55   if (initted) return 0;
56    Video* video = Video::getInstance();
57   //First Create Direct 3D Object
58   d3d=Direct3DCreate9(D3D_SDK_VERSION);
59   if (!d3d)
60   {
61     Log::getInstance()->log("OSD", Log::DEBUG, "Could not create Direct3D9 object!");
62     return 0;
63   }
64   // then create the Device
65   D3DPRESENT_PARAMETERS d3dparas;
66   ZeroMemory(&d3dparas,sizeof(d3dparas));
67   d3dparas.BackBufferWidth=video->getScreenWidth();
68   d3dparas.BackBufferHeight=video->getScreenHeight();
69   d3dparas.Windowed=TRUE;
70   d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;
71   if (d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,*((HWND*) device),
72     D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dparas,&d3ddevice)!=D3D_OK) {
73      Log::getInstance()->log("OSD", Log::DEBUG, "Could not create Direct3D9 device!");
74        return 0;
75   }
76   //TODO a render function and a device lost detection
77
78   if (!InitVertexBuffer()) {
79      Log::getInstance()->log("OSD", Log::DEBUG, "Could not create Direct3D9 vertex buf!");
80       return 0;
81   }
82
83   //Now we will create the Screen
84   screen = new SurfaceWin(Surface::SCREEN);
85   SetEvent(event);//Now all devices are ready
86   screen->create(video->getScreenWidth(), video->getScreenHeight());
87   screen->display();
88   initted = 1; // must set this here or create surface won't work
89
90   return 1;
91 }
92
93
94 int OsdWin::InitVertexBuffer() {
95   Video* video = Video::getInstance();
96   FLOAT texx=((float)video->getScreenWidth())/1024.f;
97   FLOAT texy=((float)video->getScreenHeight())/1024.f;
98   D3DCOLOR osdcolor=D3DCOLOR_RGBA(255,255,255,255);
99   osdvertices[0].c=osdcolor;
100   osdvertices[0].x=0.f-0.5f;
101   osdvertices[0].y=0.f-0.5f;
102   osdvertices[0].z=0.5f;
103   osdvertices[0].rhw=1.f;
104   osdvertices[0].u=0.f;
105   osdvertices[0].v=0.f;
106   osdvertices[1].c=osdcolor;
107   osdvertices[1].x=((float)video->getScreenWidth())-0.5f;-0.5f;
108   osdvertices[1].y=0.f-0.5f;
109   osdvertices[1].z=0.5f;
110   osdvertices[1].u=texx;
111   osdvertices[1].v=0.f;
112   osdvertices[1].rhw=1.f;
113   osdvertices[2].c=osdcolor;
114   osdvertices[2].x=((float)video->getScreenWidth())-0.5f;
115   osdvertices[2].y=((float)video->getScreenHeight())-0.5f;
116   osdvertices[2].z=0.5f;
117   osdvertices[2].rhw=1.f;
118   osdvertices[2].u=texx;
119   osdvertices[2].v=texy;
120   osdvertices[3].c=osdcolor;
121   osdvertices[3].x=0.f-0.5f;
122   osdvertices[3].y=((float)video->getScreenHeight())-0.5f;
123   osdvertices[3].z=0;
124   osdvertices[3].rhw=1.f;
125   osdvertices[3].u=0.f;
126   osdvertices[3].v=texy;
127   if (d3dvb) {
128     d3dvb->Release();
129     d3dvb=NULL;
130   }
131   if (d3ddevice->CreateVertexBuffer(4*sizeof(OSDVERTEX),0,D3DFVF_OSDVERTEX,D3DPOOL_MANAGED,
132     &d3dvb,NULL)!=D3D_OK) {
133     return 0;
134   }
135   void *pvertex=NULL;
136   if (d3dvb->Lock(0,sizeof(osdvertices),&pvertex,0)!=D3D_OK) {
137     return 0;
138   }
139   memcpy(pvertex,osdvertices,sizeof(osdvertices));
140   d3dvb->Unlock();
141   return 1;
142 }
143
144 int OsdWin::shutdown()
145 {
146   if (!initted) return 0;
147   initted = 0;
148   d3ddevice->Release();
149   d3d->Release();
150
151   return 1;
152 }
153
154 void OsdWin::screenShot(char* fileName)
155 {
156   screen->screenShot(fileName);
157 }
158
159 // This function is called from the WinMain function in order to get Screen updates
160 void OsdWin::Render()
161 {
162   if (!initted) return ;
163   if (external_driving) {
164     Sleep(5); //Sleep for 5 ms, in order to avoid blocking the other threads
165   } else {
166     InternalRendering();
167   }
168 }
169
170
171 void OsdWin::InternalRendering(){
172   WaitForSingleObject(event,INFINITE);
173   BeginPainting();
174   if (external_driving) {
175     //Copy video to Backbuffer
176   } else {
177     //Clear Background
178     d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,255),1.0f,0);
179   }
180   //Drawing the OSD
181   if (d3ddevice->BeginScene()==D3D_OK) {
182     d3ddevice->SetStreamSource(0,d3dvb,0,sizeof(OSDVERTEX));
183     d3ddevice->SetFVF(D3DFVF_OSDVERTEX);
184     d3ddevice->SetTexture(0,((SurfaceWin*)screen)->getD3dtexture());
185     //d3ddevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
186     d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP,D3DTOP_MODULATE);
187     d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
188     d3ddevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
189     d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
190     d3ddevice->SetRenderState(D3DRS_LIGHTING,FALSE);
191
192
193     d3ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN,0,2);
194     d3ddevice->EndScene();
195     //Show it to the user!
196     if (d3ddevice->Present(NULL,NULL,NULL,NULL)==D3DERR_DEVICELOST){
197       EndPainting();
198       DoLost();
199     }
200     EndPainting();
201   }
202   if (!external_driving) {
203     Sleep(4);//The User can wait for 4 milliseconds to see his changes
204   }
205 }
206
207 void OsdWin::DoLost(){
208   Log::getInstance()->log("OSD", Log::DEBUG, "Direct3D Device Lost! Reobtaining...");
209   ResetEvent(event);
210   //First we free up all resources
211   Video* video = Video::getInstance();
212   ((SurfaceWin*)screen)->ReleaseSurface();
213   d3dvb->Release();
214   d3dvb=NULL;
215   D3DPRESENT_PARAMETERS d3dparas;
216   ZeroMemory(&d3dparas,sizeof(d3dparas));
217   d3dparas.BackBufferWidth=video->getScreenWidth();
218   d3dparas.BackBufferHeight=video->getScreenHeight();
219   d3dparas.Windowed=TRUE;
220   d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;
221   if (d3ddevice->Reset(&d3dparas)!=D3D_OK){
222     return;
223   }
224   screen->create(video->getScreenWidth(), video->getScreenHeight());
225   screen->display();
226   InitVertexBuffer();
227   //Redraw Views, Chris could you add a member function to viewman, so that
228   // I can cause it to completely redraw the Views?
229   // Otherwise the OSD would be distorted after Device Lost
230   SetEvent(event);
231
232 }
233 LPDIRECT3DDEVICE9 OsdWin::getD3dDev() {
234   WaitForSingleObject(event,INFINITE);//We will only return if we are initted
235   return d3ddevice;
236 }
237
238 void OsdWin::BeginPainting() {//We synchronize calls to d3d between different threads
239   WaitForSingleObject(d3dmutex,INFINITE);
240 }
241
242 void OsdWin::EndPainting() {
243   ReleaseMutex(d3dmutex);
244 }