From 857c1d1a4dfca74417b5c9428db65b47c7978c0d Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Mon, 8 May 2006 18:46:05 +0000 Subject: [PATCH] Windows port, deadlock fix --- command.cc | 1 + osdwin.cc | 528 ++++++++++++++++++++++++++++------------------------- osdwin.h | 155 ++++++++-------- player.cc | 2 +- 4 files changed, 367 insertions(+), 319 deletions(-) diff --git a/command.cc b/command.cc index 14b3885..f77610d 100644 --- a/command.cc +++ b/command.cc @@ -683,6 +683,7 @@ void Command::doJustConnected(VConnect* vconnect) // Enter pre-keys here // handleCommand(Remote::THREE); // handleCommand(Remote::SKIPFORWARD); +// handleCommand(Remote::OK); // handleCommand(Remote::PLAY); } } diff --git a/osdwin.cc b/osdwin.cc index 8b2a2c4..962017c 100644 --- a/osdwin.cc +++ b/osdwin.cc @@ -1,244 +1,284 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "osdwin.h" -#include "mtd.h" -#include "video.h" -#include "surfacewin.h" - -//This is stuff for rendering the OSD - - -OsdWin::OsdWin() -{ - d3d=NULL; - d3ddevice=NULL; - d3dvb=NULL; - external_driving=false; - event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL); - d3dmutex = CreateMutex(NULL,FALSE,NULL); - -} - -OsdWin::~OsdWin() -{ - if (initted) shutdown(); - CloseHandle(event); - CloseHandle(d3dmutex); -} - -int OsdWin::getFD() -{ - if (!initted) return 0; - return fdOsd; -} - -int OsdWin::init(void* device) -{ - if (initted) return 0; - Video* video = Video::getInstance(); - //First Create Direct 3D Object - d3d=Direct3DCreate9(D3D_SDK_VERSION); - if (!d3d) - { - Log::getInstance()->log("OSD", Log::DEBUG, "Could not create Direct3D9 object!"); - return 0; - } - // then create the Device - D3DPRESENT_PARAMETERS d3dparas; - ZeroMemory(&d3dparas,sizeof(d3dparas)); - d3dparas.BackBufferWidth=video->getScreenWidth(); - d3dparas.BackBufferHeight=video->getScreenHeight(); - d3dparas.Windowed=TRUE; - d3dparas.SwapEffect=D3DSWAPEFFECT_COPY; - if (d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,*((HWND*) device), - D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dparas,&d3ddevice)!=D3D_OK) { - Log::getInstance()->log("OSD", Log::DEBUG, "Could not create Direct3D9 device!"); - return 0; - } - //TODO a render function and a device lost detection - - if (!InitVertexBuffer()) { - Log::getInstance()->log("OSD", Log::DEBUG, "Could not create Direct3D9 vertex buf!"); - return 0; - } - - //Now we will create the Screen - screen = new SurfaceWin(Surface::SCREEN); - SetEvent(event);//Now all devices are ready - screen->create(video->getScreenWidth(), video->getScreenHeight()); - screen->display(); - initted = 1; // must set this here or create surface won't work - - return 1; -} - - -int OsdWin::InitVertexBuffer() { - Video* video = Video::getInstance(); - FLOAT texx=((float)video->getScreenWidth())/1024.f; - FLOAT texy=((float)video->getScreenHeight())/1024.f; - D3DCOLOR osdcolor=D3DCOLOR_RGBA(255,255,255,255); - osdvertices[0].c=osdcolor; - osdvertices[0].x=0.f-0.5f; - osdvertices[0].y=0.f-0.5f; - osdvertices[0].z=0.5f; - osdvertices[0].rhw=1.f; - osdvertices[0].u=0.f; - osdvertices[0].v=0.f; - osdvertices[1].c=osdcolor; - osdvertices[1].x=((float)video->getScreenWidth())-0.5f;-0.5f; - osdvertices[1].y=0.f-0.5f; - osdvertices[1].z=0.5f; - osdvertices[1].u=texx; - osdvertices[1].v=0.f; - osdvertices[1].rhw=1.f; - osdvertices[2].c=osdcolor; - osdvertices[2].x=((float)video->getScreenWidth())-0.5f; - osdvertices[2].y=((float)video->getScreenHeight())-0.5f; - osdvertices[2].z=0.5f; - osdvertices[2].rhw=1.f; - osdvertices[2].u=texx; - osdvertices[2].v=texy; - osdvertices[3].c=osdcolor; - osdvertices[3].x=0.f-0.5f; - osdvertices[3].y=((float)video->getScreenHeight())-0.5f; - osdvertices[3].z=0; - osdvertices[3].rhw=1.f; - osdvertices[3].u=0.f; - osdvertices[3].v=texy; - if (d3dvb) { - d3dvb->Release(); - d3dvb=NULL; - } - if (d3ddevice->CreateVertexBuffer(4*sizeof(OSDVERTEX),0,D3DFVF_OSDVERTEX,D3DPOOL_MANAGED, - &d3dvb,NULL)!=D3D_OK) { - return 0; - } - void *pvertex=NULL; - if (d3dvb->Lock(0,sizeof(osdvertices),&pvertex,0)!=D3D_OK) { - return 0; - } - memcpy(pvertex,osdvertices,sizeof(osdvertices)); - d3dvb->Unlock(); - return 1; -} - -int OsdWin::shutdown() -{ - if (!initted) return 0; - initted = 0; - d3ddevice->Release(); - d3d->Release(); - - return 1; -} - -void OsdWin::screenShot(char* fileName) -{ - screen->screenShot(fileName); -} - -// This function is called from the WinMain function in order to get Screen updates -void OsdWin::Render() -{ - if (!initted) return ; - if (external_driving) { - Sleep(5); //Sleep for 5 ms, in order to avoid blocking the other threads - } else { - InternalRendering(); - } -} - - -void OsdWin::InternalRendering(){ - WaitForSingleObject(event,INFINITE); - BeginPainting(); - if (external_driving) { - //Copy video to Backbuffer - } else { - //Clear Background - d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,255),1.0f,0); - } - //Drawing the OSD - if (d3ddevice->BeginScene()==D3D_OK) { - d3ddevice->SetStreamSource(0,d3dvb,0,sizeof(OSDVERTEX)); - d3ddevice->SetFVF(D3DFVF_OSDVERTEX); - d3ddevice->SetTexture(0,((SurfaceWin*)screen)->getD3dtexture()); - //d3ddevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP,D3DTOP_MODULATE); - d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE); - d3ddevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA); - d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - d3ddevice->SetRenderState(D3DRS_LIGHTING,FALSE); - - - d3ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN,0,2); - d3ddevice->EndScene(); - //Show it to the user! - if (d3ddevice->Present(NULL,NULL,NULL,NULL)==D3DERR_DEVICELOST){ - EndPainting(); - DoLost(); - } - EndPainting(); - } - if (!external_driving) { - Sleep(4);//The User can wait for 4 milliseconds to see his changes - } -} - -void OsdWin::DoLost(){ - Log::getInstance()->log("OSD", Log::DEBUG, "Direct3D Device Lost! Reobtaining..."); - ResetEvent(event); - //First we free up all resources - Video* video = Video::getInstance(); - ((SurfaceWin*)screen)->ReleaseSurface(); - d3dvb->Release(); - d3dvb=NULL; - D3DPRESENT_PARAMETERS d3dparas; - ZeroMemory(&d3dparas,sizeof(d3dparas)); - d3dparas.BackBufferWidth=video->getScreenWidth(); - d3dparas.BackBufferHeight=video->getScreenHeight(); - d3dparas.Windowed=TRUE; - d3dparas.SwapEffect=D3DSWAPEFFECT_COPY; - if (d3ddevice->Reset(&d3dparas)!=D3D_OK){ - return; - } - screen->create(video->getScreenWidth(), video->getScreenHeight()); - screen->display(); - InitVertexBuffer(); - //Redraw Views, Chris could you add a member function to viewman, so that - // I can cause it to completely redraw the Views? - // Otherwise the OSD would be distorted after Device Lost - SetEvent(event); - -} -LPDIRECT3DDEVICE9 OsdWin::getD3dDev() { - WaitForSingleObject(event,INFINITE);//We will only return if we are initted - return d3ddevice; -} - -void OsdWin::BeginPainting() {//We synchronize calls to d3d between different threads - WaitForSingleObject(d3dmutex,INFINITE); -} - -void OsdWin::EndPainting() { - ReleaseMutex(d3dmutex); -} +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "osdwin.h" +#include "mtd.h" +#include "video.h" +#include "surfacewin.h" + +#include "dsallocator.h" + + +//This is stuff for rendering the OSD + + +OsdWin::OsdWin() +{ + d3d=NULL; + d3ddevice=NULL; + d3dvb=NULL; + d3drtsurf=NULL; + external_driving=false; + dsallocator=NULL; + event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL); + d3dmutex = CreateMutex(NULL,FALSE,NULL); + +} + +OsdWin::~OsdWin() +{ + if (initted) shutdown(); + CloseHandle(event); + CloseHandle(d3dmutex); +} + +int OsdWin::getFD() +{ + if (!initted) return 0; + return fdOsd; +} + +int OsdWin::init(void* device) +{ + if (initted) return 0; + Video* video = Video::getInstance(); + //First Create Direct 3D Object + d3d=Direct3DCreate9(D3D_SDK_VERSION); + if (!d3d) + { + Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 object!"); + return 0; + } + // then create the Device + D3DPRESENT_PARAMETERS d3dparas; + ZeroMemory(&d3dparas,sizeof(d3dparas)); + d3dparas.BackBufferWidth=video->getScreenWidth(); + d3dparas.BackBufferHeight=video->getScreenHeight(); + d3dparas.Windowed=TRUE; + d3dparas.SwapEffect=D3DSWAPEFFECT_COPY; + if (d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,*((HWND*) device), + D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dparas,&d3ddevice)!=D3D_OK) { + Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 device!"); + return 0; + } + d3ddevice->GetRenderTarget(0,&d3drtsurf); + + if (!InitVertexBuffer()) { + Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 vertex buf!"); + return 0; + } + + //Now we will create the Screen + screen = new SurfaceWin(Surface::SCREEN); + SetEvent(event);//Now all devices are ready + screen->create(video->getScreenWidth(), video->getScreenHeight()); + screen->display(); + initted = 1; // must set this here or create surface won't work + + return 1; +} + + +int OsdWin::InitVertexBuffer() { + Video* video = Video::getInstance(); + FLOAT texx=((float)video->getScreenWidth())/1024.f; + FLOAT texy=((float)video->getScreenHeight())/1024.f; + D3DCOLOR osdcolor=D3DCOLOR_RGBA(255,255,255,255); + osdvertices[0].c=osdcolor; + osdvertices[0].x=0.f-0.5f; + osdvertices[0].y=0.f-0.5f; + osdvertices[0].z=0.5f; + osdvertices[0].rhw=1.f; + osdvertices[0].u=0.f; + osdvertices[0].v=0.f; + osdvertices[1].c=osdcolor; + osdvertices[1].x=((float)video->getScreenWidth())-0.5f;-0.5f; + osdvertices[1].y=0.f-0.5f; + osdvertices[1].z=0.5f; + osdvertices[1].u=texx; + osdvertices[1].v=0.f; + osdvertices[1].rhw=1.f; + osdvertices[2].c=osdcolor; + osdvertices[2].x=((float)video->getScreenWidth())-0.5f; + osdvertices[2].y=((float)video->getScreenHeight())-0.5f; + osdvertices[2].z=0.5f; + osdvertices[2].rhw=1.f; + osdvertices[2].u=texx; + osdvertices[2].v=texy; + osdvertices[3].c=osdcolor; + osdvertices[3].x=0.f-0.5f; + osdvertices[3].y=((float)video->getScreenHeight())-0.5f; + osdvertices[3].z=0; + osdvertices[3].rhw=1.f; + osdvertices[3].u=0.f; + osdvertices[3].v=texy; + if (d3dvb) { + d3dvb->Release(); + d3dvb=NULL; + } + if (d3ddevice->CreateVertexBuffer(4*sizeof(OSDVERTEX),0,D3DFVF_OSDVERTEX,D3DPOOL_MANAGED, + &d3dvb,NULL)!=D3D_OK) { + return 0; + } + void *pvertex=NULL; + if (d3dvb->Lock(0,sizeof(osdvertices),&pvertex,0)!=D3D_OK) { + return 0; + } + memcpy(pvertex,osdvertices,sizeof(osdvertices)); + d3dvb->Unlock(); + return 1; +} + +int OsdWin::shutdown() +{ + if (!initted) return 0; + initted = 0; + d3drtsurf->Release(); + d3ddevice->Release(); + d3d->Release(); + + return 1; +} + +void OsdWin::screenShot(char* fileName) +{ + screen->screenShot(fileName); +} + +// This function is called from the WinMain function in order to get Screen updates +void OsdWin::Render() +{ + if (!initted) return ; + if (external_driving) { + Sleep(5); //Sleep for 5 ms, in order to avoid blocking the other threads + } else { + InternalRendering(NULL); + } +} + +void OsdWin::RenderDS(LPDIRECT3DSURFACE9 present){ + if (!initted) return; + if (external_driving) { + InternalRendering(present); + } +} + + +void OsdWin::InternalRendering(LPDIRECT3DSURFACE9 present){ + WaitForSingleObject(event,INFINITE); + BeginPainting(); + if (external_driving) { + //Copy video to Backbuffer + if (present!=NULL) { + d3ddevice->StretchRect(present,NULL,d3drtsurf ,NULL,D3DTEXF_LINEAR); + + } + } else { + //Clear Background + d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,255),1.0f,0); + } + //Drawing the OSD + if (d3ddevice->BeginScene()==D3D_OK) { + d3ddevice->SetStreamSource(0,d3dvb,0,sizeof(OSDVERTEX)); + d3ddevice->SetFVF(D3DFVF_OSDVERTEX); + d3ddevice->SetTexture(0,((SurfaceWin*)screen)->getD3dtexture()); + //d3ddevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP,D3DTOP_MODULATE); + d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE); + d3ddevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA); + d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + d3ddevice->SetRenderState(D3DRS_LIGHTING,FALSE); + + + d3ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN,0,2); + d3ddevice->EndScene(); + //Show it to the user! + if (d3ddevice->Present(NULL,NULL,NULL,NULL)==D3DERR_DEVICELOST){ + EndPainting(); + DoLost(); + } + EndPainting(); + } + if (!external_driving) { + Sleep(4);//The User can wait for 4 milliseconds to see his changes + } +} + +void OsdWin::DoLost(){ + Log::getInstance()->log("OSD", Log::WARN, "Direct3D Device Lost! Reobtaining..."); + ResetEvent(event); + if (external_driving && dsallocator!=NULL) { + dsallocator->LostDevice(); //Propagate the information through DS + } + //First we free up all resources + Video* video = Video::getInstance(); + ((SurfaceWin*)screen)->ReleaseSurface(); + d3drtsurf->Release(); + d3dvb->Release(); + d3dvb=NULL; + D3DPRESENT_PARAMETERS d3dparas; + ZeroMemory(&d3dparas,sizeof(d3dparas)); + d3dparas.BackBufferWidth=video->getScreenWidth(); + d3dparas.BackBufferHeight=video->getScreenHeight(); + d3dparas.Windowed=TRUE; + d3dparas.SwapEffect=D3DSWAPEFFECT_COPY; + if (d3ddevice->Reset(&d3dparas)!=D3D_OK){ + return; + } + screen->create(video->getScreenWidth(), video->getScreenHeight()); + screen->display(); + d3ddevice->GetRenderTarget(0,&d3drtsurf); + InitVertexBuffer(); + //Redraw Views, Chris could you add a member function to viewman, so that + // I can cause it to completely redraw the Views? + // Otherwise the OSD would be distorted after Device Lost + + SetEvent(event); + +} +LPDIRECT3DDEVICE9 OsdWin::getD3dDev() { + WaitForSingleObject(event,INFINITE);//We will only return if we are initted + return d3ddevice; +} + +LPDIRECT3D9 OsdWin::getD3d() { + WaitForSingleObject(event,INFINITE);//We will only return if we are initted + return d3d; +} + +void OsdWin::BeginPainting() {//We synchronize calls to d3d between different threads + WaitForSingleObject(d3dmutex,INFINITE); +} + +void OsdWin::EndPainting() { + ReleaseMutex(d3dmutex); +} + +void OsdWin::setExternalDriving(DsAllocator* dsall) { + if (dsall==NULL) { + external_driving=false; + dsallocator=NULL; + return; + } + WaitForSingleObject(event,INFINITE);//We will only return if we are initted + dsallocator=dsall; + external_driving=true; +} diff --git a/osdwin.h b/osdwin.h index a22f356..c545126 100644 --- a/osdwin.h +++ b/osdwin.h @@ -1,74 +1,81 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef OSDWIN_H -#define OSDWIN_H - -#include - -#include "osd.h" -#include "defines.h" -#include "log.h" -#include -#include - -struct OSDVERTEX -{ - FLOAT x,y,z,rhw; - DWORD c; - FLOAT u,v; -}; - -#define D3DFVF_OSDVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE| D3DFVF_TEX1) - - -class OsdWin : public Osd -{ - public: - OsdWin(); - ~OsdWin(); - - int init(void* device); - int shutdown(); - - int getFD(); - - void screenShot(char* fileName); - - LPDIRECT3DDEVICE9 getD3dDev() ; - // This function is called from the WinMain function in order to get Screen updates - void Render(); - void BeginPainting(); - void EndPainting(); -private: - LPDIRECT3D9 d3d; - LPDIRECT3DDEVICE9 d3ddevice; - LPDIRECT3DVERTEXBUFFER9 d3dvb; - // This indicates, that currently a video is played, thus the osd updates are driven by the Directshow Filtersystem - bool external_driving; - HANDLE d3dmutex; - void InternalRendering(); - void DoLost(); - int InitVertexBuffer(); - OSDVERTEX osdvertices[4]; - HANDLE event; -}; - -#endif +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef OSDWIN_H +#define OSDWIN_H + +#include + +#include "osd.h" +#include "defines.h" +#include "log.h" +#include +#include + +struct OSDVERTEX +{ + FLOAT x,y,z,rhw; + DWORD c; + FLOAT u,v; +}; + +#define D3DFVF_OSDVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE| D3DFVF_TEX1) + +class DsAllocator; + +class OsdWin : public Osd +{ + public: + OsdWin(); + ~OsdWin(); + + int init(void* device); + int shutdown(); + + int getFD(); + + void screenShot(char* fileName); + + LPDIRECT3DDEVICE9 getD3dDev() ; + LPDIRECT3D9 getD3d() ; + // This function is called from the WinMain function in order to get Screen updates + void Render(); + void RenderDS(LPDIRECT3DSURFACE9 present); + void BeginPainting(); + void EndPainting(); + void setExternalDriving(DsAllocator* dsall); +private: + LPDIRECT3D9 d3d; + LPDIRECT3DDEVICE9 d3ddevice; + LPDIRECT3DVERTEXBUFFER9 d3dvb; + LPDIRECT3DSURFACE9 d3drtsurf; + DsAllocator* dsallocator; + // This indicates, that currently a video is played, thus the osd updates are driven by the Directshow Filtersystem + bool external_driving; + HANDLE d3dmutex; + void InternalRendering(LPDIRECT3DSURFACE9 present); + void DoLost(); + int InitVertexBuffer(); + OSDVERTEX osdvertices[4]; + HANDLE event; +}; + +#endif + diff --git a/player.cc b/player.cc index 0ee83c5..621a878 100644 --- a/player.cc +++ b/player.cc @@ -191,7 +191,7 @@ void Player::toggleFastBackward() void Player::jumpToPercent(int percent) { - threadLock(); + lock(); jumpToPercentInt(percent); // unLock(); - let thread unlock this } -- 2.39.2