2 Copyright 2004-2005 Chris Tallon
\r
4 This file is part of VOMP.
\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
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
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
24 #include "videowin.h"
\r
25 #include "surfacewin.h"
\r
27 #include "dsallocator.h"
\r
30 //This is stuff for rendering the OSD
\r
39 external_driving=false;
\r
41 lastrendertime=timeGetTime();
\r
42 event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL);
\r
43 d3dmutex = CreateMutex(NULL,FALSE,NULL);
\r
49 if (initted) shutdown();
\r
51 CloseHandle(d3dmutex);
\r
56 if (!initted) return 0;
\r
60 int OsdWin::init(void* device)
\r
62 if (initted) return 0;
\r
63 Video* video = Video::getInstance();
\r
64 //First Create Direct 3D Object
\r
65 d3d=Direct3DCreate9(D3D_SDK_VERSION);
\r
68 Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 object!");
\r
71 // then create the Device
\r
72 D3DPRESENT_PARAMETERS d3dparas;
\r
73 ZeroMemory(&d3dparas,sizeof(d3dparas));
\r
74 d3dparas.BackBufferWidth=video->getScreenWidth();
\r
75 d3dparas.BackBufferHeight=video->getScreenHeight();
\r
76 d3dparas.Windowed=TRUE;
\r
77 d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;
\r
78 if (d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,*((HWND*) device),
\r
79 D3DCREATE_SOFTWARE_VERTEXPROCESSING |D3DCREATE_MULTITHREADED,&d3dparas,&d3ddevice)!=D3D_OK) {
\r
80 Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 device!");
\r
83 d3ddevice->GetRenderTarget(0,&d3drtsurf);
\r
85 if (!InitVertexBuffer()) {
\r
86 Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 vertex buf!");
\r
90 //Now we will create the Screen
\r
91 screen = new SurfaceWin(Surface::SCREEN);
\r
92 SetEvent(event);//Now all devices are ready
\r
93 screen->create(video->getScreenWidth(), video->getScreenHeight());
\r
95 initted = 1; // must set this here or create surface won't work
\r
101 int OsdWin::InitVertexBuffer() {
\r
102 Video* video = Video::getInstance();
\r
103 FLOAT texx=((float)video->getScreenWidth())/1024.f;
\r
104 FLOAT texy=((float)video->getScreenHeight())/1024.f;
\r
105 D3DCOLOR osdcolor=D3DCOLOR_RGBA(255,255,255,255);
\r
106 osdvertices[0].c=osdcolor;
\r
107 osdvertices[0].x=0.f-0.5f;
\r
108 osdvertices[0].y=0.f-0.5f;
\r
109 osdvertices[0].z=0.5f;
\r
110 osdvertices[0].rhw=1.f;
\r
111 osdvertices[0].u=0.f;
\r
112 osdvertices[0].v=0.f;
\r
113 osdvertices[1].c=osdcolor;
\r
114 osdvertices[1].x=((float)video->getScreenWidth())-0.5f;-0.5f;
\r
115 osdvertices[1].y=0.f-0.5f;
\r
116 osdvertices[1].z=0.5f;
\r
117 osdvertices[1].u=texx;
\r
118 osdvertices[1].v=0.f;
\r
119 osdvertices[1].rhw=1.f;
\r
120 osdvertices[2].c=osdcolor;
\r
121 osdvertices[2].x=((float)video->getScreenWidth())-0.5f;
\r
122 osdvertices[2].y=((float)video->getScreenHeight())-0.5f;
\r
123 osdvertices[2].z=0.5f;
\r
124 osdvertices[2].rhw=1.f;
\r
125 osdvertices[2].u=texx;
\r
126 osdvertices[2].v=texy;
\r
127 osdvertices[3].c=osdcolor;
\r
128 osdvertices[3].x=0.f-0.5f;
\r
129 osdvertices[3].y=((float)video->getScreenHeight())-0.5f;
\r
130 osdvertices[3].z=0;
\r
131 osdvertices[3].rhw=1.f;
\r
132 osdvertices[3].u=0.f;
\r
133 osdvertices[3].v=texy;
\r
138 if (d3ddevice->CreateVertexBuffer(4*sizeof(OSDVERTEX),0,D3DFVF_OSDVERTEX,D3DPOOL_MANAGED,
\r
139 &d3dvb,NULL)!=D3D_OK) {
\r
142 void *pvertex=NULL;
\r
143 if (d3dvb->Lock(0,sizeof(osdvertices),&pvertex,0)!=D3D_OK) {
\r
146 memcpy(pvertex,osdvertices,sizeof(osdvertices));
\r
151 int OsdWin::shutdown()
\r
153 if (!initted) return 0;
\r
155 d3drtsurf->Release();
\r
156 d3ddevice->Release();
\r
162 void OsdWin::screenShot(char* fileName)
\r
164 screen->screenShot(fileName);
\r
167 // This function is called from the WinMain function in order to get Screen updates
\r
168 void OsdWin::Render()
\r
170 if (!initted) return ;
\r
171 if (external_driving) {
\r
172 Sleep(5); //Sleep for 5 ms, in order to avoid blocking the other threads
\r
174 DWORD time1=timeGetTime();
\r
175 if ((time1-lastrendertime)>50) {//10 fps for OSD updates are enough, avoids tearing
\r
176 InternalRendering(NULL);
\r
177 lastrendertime=timeGetTime();
\r
186 void OsdWin::RenderDS(LPDIRECT3DSURFACE9 present){
\r
187 if (!initted) return;
\r
188 if (external_driving) {
\r
189 InternalRendering(present);
\r
194 void OsdWin::InternalRendering(LPDIRECT3DSURFACE9 present){
\r
195 WaitForSingleObject(event,INFINITE);
\r
196 WaitForSingleObject(d3dmutex,INFINITE);
\r
198 if (external_driving) {
\r
199 //Copy video to Backbuffer
\r
200 if (present!=NULL) {
\r
201 VideoWin* video =(VideoWin*) Video::getInstance();
\r
202 /*calculating destination rect */
\r
203 RECT destrect={0,0,video->getScreenWidth(),video->getScreenHeight()};
\r
204 UCHAR mode=video->getMode();
\r
206 case Video::EIGHTH:
\r
207 destrect.right=destrect.right/2;
\r
208 destrect.bottom=destrect.bottom/2;
\r
209 case Video::QUARTER:
\r
210 destrect.right=destrect.right/2+video->getPosx()*2;
\r
211 destrect.bottom=destrect.bottom/2+video->getPosy()*2;
\r
212 destrect.left=video->getPosx()*2;
\r
213 destrect.top=video->getPosy()*2;
\r
214 d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);
\r
217 D3DSURFACE_DESC surf_desc;
\r
218 present->GetDesc(&surf_desc);//for chop sides
\r
219 RECT sourcerect= {0,0,surf_desc.Width,surf_desc.Height};
\r
220 if (video->getPseudoTVsize()==Video::ASPECT4X3
\r
221 && video->getMode()==Video::NORMAL
\r
222 && video->getAspectRatio()==Video::ASPECT16X9) {
\r
223 unsigned int correction=((double) (surf_desc.Width))*4.*9./3./16.;
\r
224 sourcerect.left=(surf_desc.Width-correction)/2;
\r
225 sourcerect.right=sourcerect.left+correction;
\r
228 d3ddevice->StretchRect(present,&sourcerect,d3drtsurf ,&destrect,D3DTEXF_LINEAR);
\r
231 VideoWin* video =(VideoWin*) Video::getInstance();
\r
233 if (!video->isVideoOn()) d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);
\r
236 if (d3ddevice->BeginScene()==D3D_OK) {
\r
237 d3ddevice->SetStreamSource(0,d3dvb,0,sizeof(OSDVERTEX));
\r
238 d3ddevice->SetFVF(D3DFVF_OSDVERTEX);
\r
239 d3ddevice->SetTexture(0,((SurfaceWin*)screen)->getD3dtexture());
\r
240 //d3ddevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
\r
241 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP,D3DTOP_MODULATE);
\r
242 d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
\r
243 d3ddevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
\r
244 d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
\r
245 d3ddevice->SetRenderState(D3DRS_LIGHTING,FALSE);
\r
248 d3ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN,0,2);
\r
249 d3ddevice->EndScene();
\r
250 //Show it to the user!
\r
251 if (d3ddevice->Present(NULL,NULL,NULL,NULL)==D3DERR_DEVICELOST){
\r
257 ReleaseMutex(d3dmutex);
\r
258 if (!external_driving) {
\r
259 Sleep(4);//The User can wait for 4 milliseconds to see his changes
\r
263 void OsdWin::DoLost(){
\r
264 Log::getInstance()->log("OSD", Log::WARN, "Direct3D Device Lost! Reobtaining...");
\r
266 if (external_driving && dsallocator!=NULL) {
\r
267 dsallocator->LostDevice(); //Propagate the information through DS
\r
269 //First we free up all resources
\r
270 Video* video = Video::getInstance();
\r
271 ((SurfaceWin*)screen)->ReleaseSurface();
\r
272 d3drtsurf->Release();
\r
275 D3DPRESENT_PARAMETERS d3dparas;
\r
276 ZeroMemory(&d3dparas,sizeof(d3dparas));
\r
277 d3dparas.BackBufferWidth=video->getScreenWidth();
\r
278 d3dparas.BackBufferHeight=video->getScreenHeight();
\r
279 d3dparas.Windowed=TRUE;
\r
280 d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;
\r
281 if (d3ddevice->Reset(&d3dparas)!=D3D_OK){
\r
284 screen->create(video->getScreenWidth(), video->getScreenHeight());
\r
286 d3ddevice->GetRenderTarget(0,&d3drtsurf);
\r
287 InitVertexBuffer();
\r
288 //Redraw Views, Chris could you add a member function to viewman, so that
\r
289 // I can cause it to completely redraw the Views?
\r
290 // Otherwise the OSD would be distorted after Device Lost
\r
295 LPDIRECT3DDEVICE9 OsdWin::getD3dDev() {
\r
296 WaitForSingleObject(event,INFINITE);//We will only return if we are initted
\r
300 LPDIRECT3D9 OsdWin::getD3d() {
\r
301 WaitForSingleObject(event,INFINITE);//We will only return if we are initted
\r
305 void OsdWin::BeginPainting() {//We synchronize calls to d3d between different threads
\r
306 WaitForSingleObject(d3dmutex,INFINITE);
\r
309 void OsdWin::EndPainting() {
\r
310 ReleaseMutex(d3dmutex);
\r
313 void OsdWin::setExternalDriving(DsAllocator* dsall) {
\r
315 external_driving=false;
\r
319 WaitForSingleObject(event,INFINITE);//We will only return if we are initted
\r
321 external_driving=true;
\r
324 void OsdWin::Blank() {
\r
325 WaitForSingleObject(event,INFINITE);
\r
327 d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);
\r