1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_canvas.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #if DIRECTX_VERSION == 0x0900 32*cdf0e10cSrcweir 33*cdf0e10cSrcweir #define MAX_TEXTURE_SIZE (2048) 34*cdf0e10cSrcweir #define MIN_TEXTURE_SIZE (32) 35*cdf0e10cSrcweir //#define FAKE_MAX_NUMBER_TEXTURES (2) 36*cdf0e10cSrcweir //#define FAKE_MAX_TEXTURE_SIZE (4096) 37*cdf0e10cSrcweir 38*cdf0e10cSrcweir #define VERTEX_BUFFER_SIZE (341*3) // 1023, the size of the internal 39*cdf0e10cSrcweir // vertex buffer (must be divisable 40*cdf0e10cSrcweir // by 3, as each triangle primitive 41*cdf0e10cSrcweir // has 3 vertices) 42*cdf0e10cSrcweir 43*cdf0e10cSrcweir 44*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 45*cdf0e10cSrcweir // includes 46*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 47*cdf0e10cSrcweir #include <vcl/syschild.hxx> 48*cdf0e10cSrcweir #include <vcl/window.hxx> 49*cdf0e10cSrcweir 50*cdf0e10cSrcweir #include <canvas/debug.hxx> 51*cdf0e10cSrcweir #include <canvas/verbosetrace.hxx> 52*cdf0e10cSrcweir #include <tools/diagnose_ex.h> 53*cdf0e10cSrcweir 54*cdf0e10cSrcweir #include <canvas/elapsedtime.hxx> 55*cdf0e10cSrcweir #include <canvas/canvastools.hxx> 56*cdf0e10cSrcweir #include <canvas/rendering/icolorbuffer.hxx> 57*cdf0e10cSrcweir #include <canvas/rendering/isurface.hxx> 58*cdf0e10cSrcweir #include <canvas/rendering/irendermodule.hxx> 59*cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx> 60*cdf0e10cSrcweir #include <basegfx/vector/b2dsize.hxx> 61*cdf0e10cSrcweir #include <basegfx/vector/b2isize.hxx> 62*cdf0e10cSrcweir #include <basegfx/point/b2ipoint.hxx> 63*cdf0e10cSrcweir #include <basegfx/range/b2irectangle.hxx> 64*cdf0e10cSrcweir #include <boost/scoped_ptr.hpp> 65*cdf0e10cSrcweir #include <com/sun/star/lang/NoSupportException.hpp> 66*cdf0e10cSrcweir 67*cdf0e10cSrcweir #include "dx_rendermodule.hxx" 68*cdf0e10cSrcweir #include "dx_config.hxx" 69*cdf0e10cSrcweir 70*cdf0e10cSrcweir #undef WB_LEFT 71*cdf0e10cSrcweir #undef WB_RIGHT 72*cdf0e10cSrcweir 73*cdf0e10cSrcweir #include "dx_impltools.hxx" 74*cdf0e10cSrcweir #include <vcl/sysdata.hxx> 75*cdf0e10cSrcweir 76*cdf0e10cSrcweir #if defined(DX_DEBUG_IMAGES) 77*cdf0e10cSrcweir # if OSL_DEBUG_LEVEL > 0 78*cdf0e10cSrcweir # include <imdebug.h> 79*cdf0e10cSrcweir # undef min 80*cdf0e10cSrcweir # undef max 81*cdf0e10cSrcweir # endif 82*cdf0e10cSrcweir #endif 83*cdf0e10cSrcweir 84*cdf0e10cSrcweir using namespace ::com::sun::star; 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 87*cdf0e10cSrcweir // 'dxcanvas' namespace 88*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 89*cdf0e10cSrcweir 90*cdf0e10cSrcweir namespace dxcanvas 91*cdf0e10cSrcweir { 92*cdf0e10cSrcweir namespace 93*cdf0e10cSrcweir { 94*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 95*cdf0e10cSrcweir // monitorSupport 96*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 97*cdf0e10cSrcweir 98*cdf0e10cSrcweir class monitorSupport 99*cdf0e10cSrcweir { 100*cdf0e10cSrcweir public: 101*cdf0e10cSrcweir 102*cdf0e10cSrcweir monitorSupport() : 103*cdf0e10cSrcweir mhLibrary(LoadLibrary("user32.dll")), 104*cdf0e10cSrcweir mpMonitorFromWindow(NULL) 105*cdf0e10cSrcweir { 106*cdf0e10cSrcweir if(mhLibrary) 107*cdf0e10cSrcweir mpMonitorFromWindow = reinterpret_cast<fMonitorFromWindow>( 108*cdf0e10cSrcweir GetProcAddress( 109*cdf0e10cSrcweir mhLibrary,"MonitorFromWindow")); 110*cdf0e10cSrcweir } 111*cdf0e10cSrcweir 112*cdf0e10cSrcweir ~monitorSupport() 113*cdf0e10cSrcweir { 114*cdf0e10cSrcweir if(mhLibrary) 115*cdf0e10cSrcweir FreeLibrary(mhLibrary); 116*cdf0e10cSrcweir mhLibrary=0; 117*cdf0e10cSrcweir } 118*cdf0e10cSrcweir 119*cdf0e10cSrcweir HMONITOR MonitorFromWindow( HWND hwnd ) 120*cdf0e10cSrcweir { 121*cdf0e10cSrcweir // return adapter_default in case something went wrong... 122*cdf0e10cSrcweir if(!(mpMonitorFromWindow)) 123*cdf0e10cSrcweir return HMONITOR(0); 124*cdf0e10cSrcweir // MONITOR_DEFAULTTONEAREST 125*cdf0e10cSrcweir const DWORD dwFlags(0x00000002); 126*cdf0e10cSrcweir return mpMonitorFromWindow(hwnd,dwFlags); 127*cdf0e10cSrcweir } 128*cdf0e10cSrcweir private: 129*cdf0e10cSrcweir 130*cdf0e10cSrcweir HINSTANCE mhLibrary; 131*cdf0e10cSrcweir typedef HMONITOR (WINAPI *fMonitorFromWindow )( HWND hwnd, DWORD dwFlags ); 132*cdf0e10cSrcweir fMonitorFromWindow mpMonitorFromWindow; 133*cdf0e10cSrcweir }; 134*cdf0e10cSrcweir 135*cdf0e10cSrcweir monitorSupport aMonitorSupport; 136*cdf0e10cSrcweir 137*cdf0e10cSrcweir 138*cdf0e10cSrcweir class DXRenderModule; 139*cdf0e10cSrcweir 140*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 141*cdf0e10cSrcweir // DXSurface 142*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 143*cdf0e10cSrcweir 144*cdf0e10cSrcweir /** ISurface implemenation. 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir @attention holds the DXRenderModule via non-refcounted 147*cdf0e10cSrcweir reference! This is safe with current state of affairs, since 148*cdf0e10cSrcweir the canvas::PageManager holds surface and render module via 149*cdf0e10cSrcweir shared_ptr (and makes sure all surfaces are deleted before its 150*cdf0e10cSrcweir render module member goes out of scope). 151*cdf0e10cSrcweir */ 152*cdf0e10cSrcweir class DXSurface : public canvas::ISurface 153*cdf0e10cSrcweir { 154*cdf0e10cSrcweir public: 155*cdf0e10cSrcweir DXSurface( DXRenderModule& rRenderModule, 156*cdf0e10cSrcweir const ::basegfx::B2ISize& rSize ); 157*cdf0e10cSrcweir ~DXSurface(); 158*cdf0e10cSrcweir 159*cdf0e10cSrcweir virtual bool selectTexture(); 160*cdf0e10cSrcweir virtual bool isValid(); 161*cdf0e10cSrcweir virtual bool update( const ::basegfx::B2IPoint& rDestPos, 162*cdf0e10cSrcweir const ::basegfx::B2IRange& rSourceRect, 163*cdf0e10cSrcweir ::canvas::IColorBuffer& rSource ); 164*cdf0e10cSrcweir virtual ::basegfx::B2IVector getSize(); 165*cdf0e10cSrcweir COMReference<IDirect3DTexture9> getTexture() const; 166*cdf0e10cSrcweir 167*cdf0e10cSrcweir private: 168*cdf0e10cSrcweir /// Guard local methods against concurrent acces to RenderModule 169*cdf0e10cSrcweir class ImplRenderModuleGuard : private ::boost::noncopyable 170*cdf0e10cSrcweir { 171*cdf0e10cSrcweir public: 172*cdf0e10cSrcweir explicit inline ImplRenderModuleGuard( DXRenderModule& rRenderModule ); 173*cdf0e10cSrcweir inline ~ImplRenderModuleGuard(); 174*cdf0e10cSrcweir 175*cdf0e10cSrcweir private: 176*cdf0e10cSrcweir DXRenderModule& mrRenderModule; 177*cdf0e10cSrcweir }; 178*cdf0e10cSrcweir 179*cdf0e10cSrcweir DXRenderModule& mrRenderModule; 180*cdf0e10cSrcweir COMReference<IDirect3DTexture9> mpTexture; 181*cdf0e10cSrcweir 182*cdf0e10cSrcweir ::basegfx::B2IVector maSize; 183*cdf0e10cSrcweir }; 184*cdf0e10cSrcweir 185*cdf0e10cSrcweir 186*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 187*cdf0e10cSrcweir // DXRenderModule 188*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 189*cdf0e10cSrcweir 190*cdf0e10cSrcweir /// Default implementation of IDXRenderModule 191*cdf0e10cSrcweir class DXRenderModule : public IDXRenderModule 192*cdf0e10cSrcweir { 193*cdf0e10cSrcweir public: 194*cdf0e10cSrcweir explicit DXRenderModule( const ::Window& rWindow ); 195*cdf0e10cSrcweir ~DXRenderModule(); 196*cdf0e10cSrcweir 197*cdf0e10cSrcweir virtual void lock() const { maMutex.acquire(); } 198*cdf0e10cSrcweir virtual void unlock() const { maMutex.release(); } 199*cdf0e10cSrcweir 200*cdf0e10cSrcweir virtual COMReference<IDirect3DSurface9> 201*cdf0e10cSrcweir createSystemMemorySurface( const ::basegfx::B2IVector& rSize ); 202*cdf0e10cSrcweir virtual void disposing(); 203*cdf0e10cSrcweir virtual HWND getHWND() const { return mhWnd; } 204*cdf0e10cSrcweir virtual void screenShot(); 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir virtual bool flip( const ::basegfx::B2IRectangle& rUpdateArea, 207*cdf0e10cSrcweir const ::basegfx::B2IRectangle& rCurrWindowArea ); 208*cdf0e10cSrcweir 209*cdf0e10cSrcweir virtual void resize( const ::basegfx::B2IRange& rect ); 210*cdf0e10cSrcweir virtual ::basegfx::B2IVector getPageSize(); 211*cdf0e10cSrcweir virtual ::canvas::ISurfaceSharedPtr createSurface( const ::basegfx::B2IVector& surfaceSize ); 212*cdf0e10cSrcweir virtual void beginPrimitive( PrimitiveType eType ); 213*cdf0e10cSrcweir virtual void endPrimitive(); 214*cdf0e10cSrcweir virtual void pushVertex( const ::canvas::Vertex& vertex ); 215*cdf0e10cSrcweir virtual bool isError(); 216*cdf0e10cSrcweir 217*cdf0e10cSrcweir COMReference<IDirect3DDevice9> getDevice() { return mpDevice; } 218*cdf0e10cSrcweir 219*cdf0e10cSrcweir void flushVertexCache(); 220*cdf0e10cSrcweir void commitVertexCache(); 221*cdf0e10cSrcweir 222*cdf0e10cSrcweir private: 223*cdf0e10cSrcweir 224*cdf0e10cSrcweir bool create( const ::Window& rWindow ); 225*cdf0e10cSrcweir bool createDevice(); 226*cdf0e10cSrcweir bool verifyDevice( const UINT nAdapter ); 227*cdf0e10cSrcweir UINT getAdapterFromWindow(); 228*cdf0e10cSrcweir 229*cdf0e10cSrcweir /** This object represents the DirectX state machine. In order 230*cdf0e10cSrcweir to serialize access to DirectX's global state, a global 231*cdf0e10cSrcweir mutex is required. 232*cdf0e10cSrcweir */ 233*cdf0e10cSrcweir static ::osl::Mutex maMutex; 234*cdf0e10cSrcweir 235*cdf0e10cSrcweir HWND mhWnd; 236*cdf0e10cSrcweir COMReference<IDirect3DDevice9> mpDevice; 237*cdf0e10cSrcweir COMReference<IDirect3D9> mpDirect3D9; 238*cdf0e10cSrcweir COMReference<IDirect3DSwapChain9> mpSwapChain; 239*cdf0e10cSrcweir COMReference<IDirect3DVertexBuffer9> mpVertexBuffer; 240*cdf0e10cSrcweir ::canvas::ISurfaceSharedPtr mpTexture; 241*cdf0e10cSrcweir ::boost::scoped_ptr<SystemChildWindow> mpWindow; 242*cdf0e10cSrcweir ::basegfx::B2IVector maSize; 243*cdf0e10cSrcweir typedef std::vector<canvas::Vertex> vertexCache_t; 244*cdf0e10cSrcweir vertexCache_t maVertexCache; 245*cdf0e10cSrcweir std::size_t mnCount; 246*cdf0e10cSrcweir int mnBeginSceneCount; 247*cdf0e10cSrcweir bool mbCanUseDynamicTextures; 248*cdf0e10cSrcweir bool mbError; 249*cdf0e10cSrcweir PrimitiveType meType; 250*cdf0e10cSrcweir ::basegfx::B2IVector maPageSize; 251*cdf0e10cSrcweir D3DPRESENT_PARAMETERS mad3dpp; 252*cdf0e10cSrcweir 253*cdf0e10cSrcweir inline bool isDisposed() const { return (mhWnd==NULL); } 254*cdf0e10cSrcweir 255*cdf0e10cSrcweir struct dxvertex 256*cdf0e10cSrcweir { 257*cdf0e10cSrcweir float x,y,z,rhw; 258*cdf0e10cSrcweir DWORD diffuse; 259*cdf0e10cSrcweir float u,v; 260*cdf0e10cSrcweir }; 261*cdf0e10cSrcweir 262*cdf0e10cSrcweir std::size_t maNumVertices; 263*cdf0e10cSrcweir std::size_t maWriteIndex; 264*cdf0e10cSrcweir std::size_t maReadIndex; 265*cdf0e10cSrcweir }; 266*cdf0e10cSrcweir 267*cdf0e10cSrcweir ::osl::Mutex DXRenderModule::maMutex; 268*cdf0e10cSrcweir 269*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 270*cdf0e10cSrcweir // DXSurface::ImplRenderModuleGuard 271*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 272*cdf0e10cSrcweir 273*cdf0e10cSrcweir inline DXSurface::ImplRenderModuleGuard::ImplRenderModuleGuard( 274*cdf0e10cSrcweir DXRenderModule& rRenderModule ) : 275*cdf0e10cSrcweir mrRenderModule( rRenderModule ) 276*cdf0e10cSrcweir { 277*cdf0e10cSrcweir mrRenderModule.lock(); 278*cdf0e10cSrcweir } 279*cdf0e10cSrcweir 280*cdf0e10cSrcweir inline DXSurface::ImplRenderModuleGuard::~ImplRenderModuleGuard() 281*cdf0e10cSrcweir { 282*cdf0e10cSrcweir mrRenderModule.unlock(); 283*cdf0e10cSrcweir } 284*cdf0e10cSrcweir 285*cdf0e10cSrcweir #ifdef FAKE_MAX_NUMBER_TEXTURES 286*cdf0e10cSrcweir static sal_uInt32 gNumSurfaces = 0; 287*cdf0e10cSrcweir #endif 288*cdf0e10cSrcweir 289*cdf0e10cSrcweir void fillRect( sal_uInt32 *pDest, 290*cdf0e10cSrcweir sal_uInt32 dwWidth, 291*cdf0e10cSrcweir sal_uInt32 dwHeight, 292*cdf0e10cSrcweir sal_uInt32 dwPitch, 293*cdf0e10cSrcweir sal_uInt32 dwColor ) 294*cdf0e10cSrcweir { 295*cdf0e10cSrcweir for(sal_uInt32 i=0; i<dwWidth; ++i) 296*cdf0e10cSrcweir { 297*cdf0e10cSrcweir pDest[i]=dwColor; 298*cdf0e10cSrcweir pDest[((dwHeight-1)*dwPitch)+i]=dwColor; 299*cdf0e10cSrcweir } 300*cdf0e10cSrcweir 301*cdf0e10cSrcweir for(sal_uInt32 j=0; j<dwHeight; ++j) 302*cdf0e10cSrcweir { 303*cdf0e10cSrcweir pDest[0]=dwColor; 304*cdf0e10cSrcweir pDest[dwWidth-1]=dwColor; 305*cdf0e10cSrcweir pDest += dwPitch; 306*cdf0e10cSrcweir } 307*cdf0e10cSrcweir } 308*cdf0e10cSrcweir 309*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 310*cdf0e10cSrcweir // DXSurface::DXSurface 311*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 312*cdf0e10cSrcweir 313*cdf0e10cSrcweir DXSurface::DXSurface( DXRenderModule& rRenderModule, 314*cdf0e10cSrcweir const ::basegfx::B2ISize& rSize ) : 315*cdf0e10cSrcweir mrRenderModule(rRenderModule), 316*cdf0e10cSrcweir mpTexture(NULL), 317*cdf0e10cSrcweir maSize() 318*cdf0e10cSrcweir { 319*cdf0e10cSrcweir ImplRenderModuleGuard aGuard( mrRenderModule ); 320*cdf0e10cSrcweir 321*cdf0e10cSrcweir #ifdef FAKE_MAX_NUMBER_TEXTURES 322*cdf0e10cSrcweir ++gNumSurfaces; 323*cdf0e10cSrcweir if(gNumSurfaces >= FAKE_MAX_NUMBER_TEXTURES) 324*cdf0e10cSrcweir return; 325*cdf0e10cSrcweir #endif 326*cdf0e10cSrcweir 327*cdf0e10cSrcweir #ifdef FAKE_MAX_TEXTURE_SIZE 328*cdf0e10cSrcweir if(rSize.getX() > FAKE_MAX_TEXTURE_SIZE) 329*cdf0e10cSrcweir return; 330*cdf0e10cSrcweir if(rSize.getY() > FAKE_MAX_TEXTURE_SIZE) 331*cdf0e10cSrcweir return; 332*cdf0e10cSrcweir #endif 333*cdf0e10cSrcweir 334*cdf0e10cSrcweir ENSURE_ARG_OR_THROW(rSize.getX() > 0 && rSize.getY() > 0, 335*cdf0e10cSrcweir "DXSurface::DXSurface(): request for zero-sized surface"); 336*cdf0e10cSrcweir 337*cdf0e10cSrcweir COMReference<IDirect3DDevice9> pDevice(rRenderModule.getDevice()); 338*cdf0e10cSrcweir 339*cdf0e10cSrcweir IDirect3DTexture9 *pTexture(NULL); 340*cdf0e10cSrcweir if(FAILED(pDevice->CreateTexture( 341*cdf0e10cSrcweir rSize.getX(), 342*cdf0e10cSrcweir rSize.getY(), 343*cdf0e10cSrcweir 1,0,D3DFMT_A8R8G8B8, 344*cdf0e10cSrcweir D3DPOOL_MANAGED, 345*cdf0e10cSrcweir &pTexture,NULL))) 346*cdf0e10cSrcweir return; 347*cdf0e10cSrcweir 348*cdf0e10cSrcweir mpTexture=COMReference<IDirect3DTexture9>(pTexture); 349*cdf0e10cSrcweir maSize = rSize; 350*cdf0e10cSrcweir } 351*cdf0e10cSrcweir 352*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 353*cdf0e10cSrcweir // DXSurface::~DXSurface 354*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 355*cdf0e10cSrcweir 356*cdf0e10cSrcweir DXSurface::~DXSurface() 357*cdf0e10cSrcweir { 358*cdf0e10cSrcweir ImplRenderModuleGuard aGuard( mrRenderModule ); 359*cdf0e10cSrcweir 360*cdf0e10cSrcweir #ifdef FAKE_MAX_NUMBER_TEXTURES 361*cdf0e10cSrcweir gNumSurfaces--; 362*cdf0e10cSrcweir #endif 363*cdf0e10cSrcweir } 364*cdf0e10cSrcweir 365*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 366*cdf0e10cSrcweir // DXSurface::selectTexture 367*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 368*cdf0e10cSrcweir 369*cdf0e10cSrcweir bool DXSurface::selectTexture() 370*cdf0e10cSrcweir { 371*cdf0e10cSrcweir ImplRenderModuleGuard aGuard( mrRenderModule ); 372*cdf0e10cSrcweir mrRenderModule.flushVertexCache(); 373*cdf0e10cSrcweir COMReference<IDirect3DDevice9> pDevice(mrRenderModule.getDevice()); 374*cdf0e10cSrcweir 375*cdf0e10cSrcweir if( FAILED(pDevice->SetTexture(0,mpTexture.get())) ) 376*cdf0e10cSrcweir return false; 377*cdf0e10cSrcweir 378*cdf0e10cSrcweir return true; 379*cdf0e10cSrcweir } 380*cdf0e10cSrcweir 381*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 382*cdf0e10cSrcweir // DXSurface::isValid 383*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 384*cdf0e10cSrcweir 385*cdf0e10cSrcweir bool DXSurface::isValid() 386*cdf0e10cSrcweir { 387*cdf0e10cSrcweir ImplRenderModuleGuard aGuard( mrRenderModule ); 388*cdf0e10cSrcweir 389*cdf0e10cSrcweir if(!(mpTexture.is())) 390*cdf0e10cSrcweir return false; 391*cdf0e10cSrcweir return true; 392*cdf0e10cSrcweir } 393*cdf0e10cSrcweir 394*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 395*cdf0e10cSrcweir // DXSurface::update 396*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 397*cdf0e10cSrcweir 398*cdf0e10cSrcweir bool DXSurface::update( const ::basegfx::B2IPoint& rDestPos, 399*cdf0e10cSrcweir const ::basegfx::B2IRange& rSourceRect, 400*cdf0e10cSrcweir ::canvas::IColorBuffer& rSource ) 401*cdf0e10cSrcweir { 402*cdf0e10cSrcweir ImplRenderModuleGuard aGuard( mrRenderModule ); 403*cdf0e10cSrcweir 404*cdf0e10cSrcweir // can't update if surface is not valid, that means 405*cdf0e10cSrcweir // either not existent nor restored... 406*cdf0e10cSrcweir if(!(isValid())) 407*cdf0e10cSrcweir return false; 408*cdf0e10cSrcweir 409*cdf0e10cSrcweir D3DLOCKED_RECT aLockedRect; 410*cdf0e10cSrcweir RECT rect; 411*cdf0e10cSrcweir rect.left = std::max(sal_Int32(0),rDestPos.getX()); 412*cdf0e10cSrcweir rect.top = std::max(sal_Int32(0),rDestPos.getY()); 413*cdf0e10cSrcweir // to avoid interpolation artifacts from other textures, 414*cdf0e10cSrcweir // the surface manager allocates one pixel gap between 415*cdf0e10cSrcweir // them. Clear that to transparent. 416*cdf0e10cSrcweir rect.right = std::min(maSize.getX(), 417*cdf0e10cSrcweir rect.left + sal_Int32(rSourceRect.getWidth()+1)); 418*cdf0e10cSrcweir rect.bottom = std::min(maSize.getY(), 419*cdf0e10cSrcweir rect.top + sal_Int32(rSourceRect.getHeight()+1)); 420*cdf0e10cSrcweir const bool bClearRightColumn( rect.right < maSize.getX() ); 421*cdf0e10cSrcweir const bool bClearBottomRow( rect.bottom < maSize.getY() ); 422*cdf0e10cSrcweir 423*cdf0e10cSrcweir if(SUCCEEDED(mpTexture->LockRect(0,&aLockedRect,&rect,D3DLOCK_NOSYSLOCK))) 424*cdf0e10cSrcweir { 425*cdf0e10cSrcweir if(sal_uInt8* pImage = rSource.lock()) 426*cdf0e10cSrcweir { 427*cdf0e10cSrcweir switch( rSource.getFormat() ) 428*cdf0e10cSrcweir { 429*cdf0e10cSrcweir case ::canvas::IColorBuffer::FMT_A8R8G8B8: 430*cdf0e10cSrcweir { 431*cdf0e10cSrcweir const std::size_t nSourceBytesPerPixel(4); 432*cdf0e10cSrcweir const std::size_t nSourcePitchInBytes(rSource.getStride()); 433*cdf0e10cSrcweir pImage += rSourceRect.getMinY()*nSourcePitchInBytes; 434*cdf0e10cSrcweir pImage += rSourceRect.getMinX()*nSourceBytesPerPixel; 435*cdf0e10cSrcweir 436*cdf0e10cSrcweir // calculate the destination memory address 437*cdf0e10cSrcweir sal_uInt8 *pDst = (sal_uInt8*)aLockedRect.pBits; 438*cdf0e10cSrcweir 439*cdf0e10cSrcweir const sal_uInt32 nNumBytesToCopy( 440*cdf0e10cSrcweir static_cast<sal_uInt32>( 441*cdf0e10cSrcweir rSourceRect.getWidth())* 442*cdf0e10cSrcweir nSourceBytesPerPixel); 443*cdf0e10cSrcweir const sal_uInt64 nNumLines(rSourceRect.getHeight()); 444*cdf0e10cSrcweir 445*cdf0e10cSrcweir for(sal_uInt32 i=0; i<nNumLines; ++i) 446*cdf0e10cSrcweir { 447*cdf0e10cSrcweir rtl_copyMemory(pDst,pImage,nNumBytesToCopy); 448*cdf0e10cSrcweir 449*cdf0e10cSrcweir if( bClearRightColumn ) 450*cdf0e10cSrcweir { 451*cdf0e10cSrcweir // to avoid interpolation artifacts 452*cdf0e10cSrcweir // from other textures, the surface 453*cdf0e10cSrcweir // manager allocates one pixel gap 454*cdf0e10cSrcweir // between them. Clear that to 455*cdf0e10cSrcweir // transparent. 456*cdf0e10cSrcweir pDst[nNumBytesToCopy] = 457*cdf0e10cSrcweir pDst[nNumBytesToCopy+1] = 458*cdf0e10cSrcweir pDst[nNumBytesToCopy+2] = 459*cdf0e10cSrcweir pDst[nNumBytesToCopy+3] = 0x00; 460*cdf0e10cSrcweir } 461*cdf0e10cSrcweir pDst += aLockedRect.Pitch; 462*cdf0e10cSrcweir pImage += nSourcePitchInBytes; 463*cdf0e10cSrcweir } 464*cdf0e10cSrcweir 465*cdf0e10cSrcweir if( bClearBottomRow ) 466*cdf0e10cSrcweir rtl_zeroMemory(pDst,nNumBytesToCopy+4); 467*cdf0e10cSrcweir } 468*cdf0e10cSrcweir break; 469*cdf0e10cSrcweir 470*cdf0e10cSrcweir case ::canvas::IColorBuffer::FMT_R8G8B8: 471*cdf0e10cSrcweir { 472*cdf0e10cSrcweir const std::size_t nSourceBytesPerPixel(3); 473*cdf0e10cSrcweir const std::size_t nSourcePitchInBytes(rSource.getStride()); 474*cdf0e10cSrcweir pImage += rSourceRect.getMinY()*nSourcePitchInBytes; 475*cdf0e10cSrcweir pImage += rSourceRect.getMinX()*nSourceBytesPerPixel; 476*cdf0e10cSrcweir 477*cdf0e10cSrcweir // calculate the destination memory address 478*cdf0e10cSrcweir sal_uInt8 *pDst = (sal_uInt8*)aLockedRect.pBits; 479*cdf0e10cSrcweir 480*cdf0e10cSrcweir const sal_Int32 nNumColumns( 481*cdf0e10cSrcweir sal::static_int_cast<sal_Int32>(rSourceRect.getWidth())); 482*cdf0e10cSrcweir const sal_Int32 nNumLines( 483*cdf0e10cSrcweir sal::static_int_cast<sal_Int32>(rSourceRect.getHeight())); 484*cdf0e10cSrcweir for(sal_Int32 i=0; i<nNumLines; ++i) 485*cdf0e10cSrcweir { 486*cdf0e10cSrcweir sal_uInt32 *pDstScanline = reinterpret_cast<sal_uInt32 *>(pDst); 487*cdf0e10cSrcweir sal_uInt8 *pSrcScanline = reinterpret_cast<sal_uInt8 *>(pImage); 488*cdf0e10cSrcweir 489*cdf0e10cSrcweir for(sal_Int32 x=0; x<nNumColumns; ++x) 490*cdf0e10cSrcweir { 491*cdf0e10cSrcweir sal_uInt32 color(0xFF000000); 492*cdf0e10cSrcweir color |= pSrcScanline[2]<<16; 493*cdf0e10cSrcweir color |= pSrcScanline[1]<<8; 494*cdf0e10cSrcweir color |= pSrcScanline[0]; 495*cdf0e10cSrcweir pSrcScanline += 3; 496*cdf0e10cSrcweir *pDstScanline++ = color; 497*cdf0e10cSrcweir } 498*cdf0e10cSrcweir if( bClearRightColumn ) 499*cdf0e10cSrcweir *pDstScanline++ = 0xFF000000; 500*cdf0e10cSrcweir 501*cdf0e10cSrcweir pDst += aLockedRect.Pitch; 502*cdf0e10cSrcweir pImage += nSourcePitchInBytes; 503*cdf0e10cSrcweir } 504*cdf0e10cSrcweir 505*cdf0e10cSrcweir if( bClearBottomRow ) 506*cdf0e10cSrcweir rtl_zeroMemory(pDst,4*(nNumColumns+1)); 507*cdf0e10cSrcweir } 508*cdf0e10cSrcweir break; 509*cdf0e10cSrcweir 510*cdf0e10cSrcweir case ::canvas::IColorBuffer::FMT_X8R8G8B8: 511*cdf0e10cSrcweir { 512*cdf0e10cSrcweir const std::size_t nSourceBytesPerPixel(4); 513*cdf0e10cSrcweir const std::size_t nSourcePitchInBytes(rSource.getStride()); 514*cdf0e10cSrcweir pImage += rSourceRect.getMinY()*nSourcePitchInBytes; 515*cdf0e10cSrcweir pImage += rSourceRect.getMinX()*nSourceBytesPerPixel; 516*cdf0e10cSrcweir 517*cdf0e10cSrcweir // calculate the destination memory address 518*cdf0e10cSrcweir sal_uInt8 *pDst = (sal_uInt8*)aLockedRect.pBits; 519*cdf0e10cSrcweir 520*cdf0e10cSrcweir const sal_Int32 nNumLines( 521*cdf0e10cSrcweir sal::static_int_cast<sal_Int32>(rSourceRect.getHeight())); 522*cdf0e10cSrcweir const sal_Int32 nNumColumns( 523*cdf0e10cSrcweir sal::static_int_cast<sal_Int32>(rSourceRect.getWidth())); 524*cdf0e10cSrcweir for(sal_Int32 i=0; i<nNumLines; ++i) 525*cdf0e10cSrcweir { 526*cdf0e10cSrcweir sal_uInt32 *pSrc32 = reinterpret_cast<sal_uInt32 *>(pImage); 527*cdf0e10cSrcweir sal_uInt32 *pDst32 = reinterpret_cast<sal_uInt32 *>(pDst); 528*cdf0e10cSrcweir for(sal_Int32 j=0; j<nNumColumns; ++j) 529*cdf0e10cSrcweir pDst32[j] = 0xFF000000 | pSrc32[j]; 530*cdf0e10cSrcweir 531*cdf0e10cSrcweir if( bClearRightColumn ) 532*cdf0e10cSrcweir pDst32[nNumColumns] = 0xFF000000; 533*cdf0e10cSrcweir 534*cdf0e10cSrcweir pDst += aLockedRect.Pitch; 535*cdf0e10cSrcweir pImage += nSourcePitchInBytes; 536*cdf0e10cSrcweir } 537*cdf0e10cSrcweir 538*cdf0e10cSrcweir if( bClearBottomRow ) 539*cdf0e10cSrcweir rtl_zeroMemory(pDst,4*(nNumColumns+1)); 540*cdf0e10cSrcweir } 541*cdf0e10cSrcweir break; 542*cdf0e10cSrcweir 543*cdf0e10cSrcweir default: 544*cdf0e10cSrcweir ENSURE_OR_RETURN_FALSE(false, 545*cdf0e10cSrcweir "DXSurface::update(): Unknown/unimplemented buffer format" ); 546*cdf0e10cSrcweir break; 547*cdf0e10cSrcweir } 548*cdf0e10cSrcweir 549*cdf0e10cSrcweir rSource.unlock(); 550*cdf0e10cSrcweir } 551*cdf0e10cSrcweir 552*cdf0e10cSrcweir return SUCCEEDED(mpTexture->UnlockRect(0)); 553*cdf0e10cSrcweir } 554*cdf0e10cSrcweir 555*cdf0e10cSrcweir return true; 556*cdf0e10cSrcweir } 557*cdf0e10cSrcweir 558*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 559*cdf0e10cSrcweir // DXSurface::getSize 560*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 561*cdf0e10cSrcweir 562*cdf0e10cSrcweir ::basegfx::B2IVector DXSurface::getSize() 563*cdf0e10cSrcweir { 564*cdf0e10cSrcweir return maSize; 565*cdf0e10cSrcweir } 566*cdf0e10cSrcweir 567*cdf0e10cSrcweir COMReference<IDirect3DTexture9> DXSurface::getTexture() const 568*cdf0e10cSrcweir { 569*cdf0e10cSrcweir return mpTexture; 570*cdf0e10cSrcweir } 571*cdf0e10cSrcweir 572*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 573*cdf0e10cSrcweir // DXRenderModule::DXRenderModule 574*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 575*cdf0e10cSrcweir 576*cdf0e10cSrcweir DXRenderModule::DXRenderModule( const ::Window& rWindow ) : 577*cdf0e10cSrcweir mhWnd(0), 578*cdf0e10cSrcweir mpDevice(), 579*cdf0e10cSrcweir mpDirect3D9(), 580*cdf0e10cSrcweir mpSwapChain(), 581*cdf0e10cSrcweir mpVertexBuffer(), 582*cdf0e10cSrcweir mpTexture(), 583*cdf0e10cSrcweir maSize(), 584*cdf0e10cSrcweir maVertexCache(), 585*cdf0e10cSrcweir mnCount(0), 586*cdf0e10cSrcweir mnBeginSceneCount(0), 587*cdf0e10cSrcweir mbCanUseDynamicTextures(false), 588*cdf0e10cSrcweir mbError( false ), 589*cdf0e10cSrcweir meType( PRIMITIVE_TYPE_UNKNOWN ), 590*cdf0e10cSrcweir maPageSize(), 591*cdf0e10cSrcweir mad3dpp(), 592*cdf0e10cSrcweir maNumVertices( VERTEX_BUFFER_SIZE ), 593*cdf0e10cSrcweir maWriteIndex(0), 594*cdf0e10cSrcweir maReadIndex(0) 595*cdf0e10cSrcweir { 596*cdf0e10cSrcweir // TODO(P2): get rid of those fine-grained locking 597*cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 598*cdf0e10cSrcweir 599*cdf0e10cSrcweir if(!(create(rWindow))) 600*cdf0e10cSrcweir { 601*cdf0e10cSrcweir throw lang::NoSupportException( 602*cdf0e10cSrcweir ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 603*cdf0e10cSrcweir "Could not create DirectX device!") ),NULL); 604*cdf0e10cSrcweir } 605*cdf0e10cSrcweir 606*cdf0e10cSrcweir // allocate a single texture surface which can be used later. 607*cdf0e10cSrcweir // we also use this to calibrate the page size. 608*cdf0e10cSrcweir ::basegfx::B2IVector aPageSize(maPageSize); 609*cdf0e10cSrcweir while(true) 610*cdf0e10cSrcweir { 611*cdf0e10cSrcweir mpTexture = ::canvas::ISurfaceSharedPtr( 612*cdf0e10cSrcweir new DXSurface(*this,aPageSize)); 613*cdf0e10cSrcweir if(mpTexture->isValid()) 614*cdf0e10cSrcweir break; 615*cdf0e10cSrcweir 616*cdf0e10cSrcweir aPageSize.setX(aPageSize.getX()>>1); 617*cdf0e10cSrcweir aPageSize.setY(aPageSize.getY()>>1); 618*cdf0e10cSrcweir if((aPageSize.getX() < MIN_TEXTURE_SIZE) || 619*cdf0e10cSrcweir (aPageSize.getY() < MIN_TEXTURE_SIZE)) 620*cdf0e10cSrcweir { 621*cdf0e10cSrcweir throw lang::NoSupportException( 622*cdf0e10cSrcweir ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 623*cdf0e10cSrcweir "Could not create DirectX device - " 624*cdf0e10cSrcweir "insufficient texture space!") ),NULL); 625*cdf0e10cSrcweir } 626*cdf0e10cSrcweir } 627*cdf0e10cSrcweir maPageSize=aPageSize; 628*cdf0e10cSrcweir 629*cdf0e10cSrcweir IDirect3DVertexBuffer9 *pVB(NULL); 630*cdf0e10cSrcweir DWORD aFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1); 631*cdf0e10cSrcweir if( FAILED(mpDevice->CreateVertexBuffer(sizeof(dxvertex)*maNumVertices, 632*cdf0e10cSrcweir D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, 633*cdf0e10cSrcweir aFVF, 634*cdf0e10cSrcweir D3DPOOL_DEFAULT, 635*cdf0e10cSrcweir &pVB, 636*cdf0e10cSrcweir NULL)) ) 637*cdf0e10cSrcweir { 638*cdf0e10cSrcweir throw lang::NoSupportException( 639*cdf0e10cSrcweir ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 640*cdf0e10cSrcweir "Could not create DirectX device - out of memory!")),NULL); 641*cdf0e10cSrcweir } 642*cdf0e10cSrcweir 643*cdf0e10cSrcweir mpVertexBuffer=COMReference<IDirect3DVertexBuffer9>(pVB); 644*cdf0e10cSrcweir } 645*cdf0e10cSrcweir 646*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 647*cdf0e10cSrcweir // DXRenderModule::~DXRenderModule 648*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 649*cdf0e10cSrcweir 650*cdf0e10cSrcweir DXRenderModule::~DXRenderModule() 651*cdf0e10cSrcweir { 652*cdf0e10cSrcweir disposing(); 653*cdf0e10cSrcweir } 654*cdf0e10cSrcweir 655*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 656*cdf0e10cSrcweir // DXRenderModule::disposing 657*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 658*cdf0e10cSrcweir 659*cdf0e10cSrcweir void DXRenderModule::disposing() 660*cdf0e10cSrcweir { 661*cdf0e10cSrcweir if(!(mhWnd)) 662*cdf0e10cSrcweir return; 663*cdf0e10cSrcweir 664*cdf0e10cSrcweir mpTexture.reset(); 665*cdf0e10cSrcweir mpWindow.reset(); 666*cdf0e10cSrcweir mhWnd=NULL; 667*cdf0e10cSrcweir 668*cdf0e10cSrcweir // refrain from releasing the DX9 objects. We're the only 669*cdf0e10cSrcweir // ones holding references to them, and it might be 670*cdf0e10cSrcweir // dangerous to destroy the DX9 device, before all other 671*cdf0e10cSrcweir // objects are dead. 672*cdf0e10cSrcweir } 673*cdf0e10cSrcweir 674*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 675*cdf0e10cSrcweir // DXRenderModule::create 676*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 677*cdf0e10cSrcweir 678*cdf0e10cSrcweir bool DXRenderModule::create( const ::Window& rWindow ) 679*cdf0e10cSrcweir { 680*cdf0e10cSrcweir // TODO(P2): get rid of those fine-grained locking 681*cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 682*cdf0e10cSrcweir 683*cdf0e10cSrcweir maVertexCache.reserve(1024); 684*cdf0e10cSrcweir 685*cdf0e10cSrcweir mpWindow.reset( 686*cdf0e10cSrcweir new SystemChildWindow( 687*cdf0e10cSrcweir const_cast<Window *>(&rWindow), 0) ); 688*cdf0e10cSrcweir 689*cdf0e10cSrcweir // system child window must not receive mouse events 690*cdf0e10cSrcweir mpWindow->SetMouseTransparent( TRUE ); 691*cdf0e10cSrcweir 692*cdf0e10cSrcweir // parent should receive paint messages as well 693*cdf0e10cSrcweir // [PARENTCLIPMODE_NOCLIP], the argument is here 694*cdf0e10cSrcweir // passed as plain numeric value since the stupid 695*cdf0e10cSrcweir // define utilizes a USHORT cast. 696*cdf0e10cSrcweir mpWindow->SetParentClipMode(0x0002); 697*cdf0e10cSrcweir 698*cdf0e10cSrcweir // the system child window must not clear its background 699*cdf0e10cSrcweir mpWindow->EnableEraseBackground( sal_False ); 700*cdf0e10cSrcweir 701*cdf0e10cSrcweir mpWindow->SetControlForeground(); 702*cdf0e10cSrcweir mpWindow->SetControlBackground(); 703*cdf0e10cSrcweir mpWindow->EnablePaint(sal_False); 704*cdf0e10cSrcweir 705*cdf0e10cSrcweir const SystemEnvData *pData = mpWindow->GetSystemData(); 706*cdf0e10cSrcweir const HWND hwnd(reinterpret_cast<HWND>(pData->hWnd)); 707*cdf0e10cSrcweir mhWnd = const_cast<HWND>(hwnd); 708*cdf0e10cSrcweir 709*cdf0e10cSrcweir ENSURE_OR_THROW( IsWindow( reinterpret_cast<HWND>(mhWnd) ), 710*cdf0e10cSrcweir "DXRenderModule::create() No valid HWND given." ); 711*cdf0e10cSrcweir 712*cdf0e10cSrcweir // retrieve position and size of the parent window 713*cdf0e10cSrcweir const ::Size &rSizePixel(rWindow.GetSizePixel()); 714*cdf0e10cSrcweir 715*cdf0e10cSrcweir // remember the size of the parent window, since we 716*cdf0e10cSrcweir // need to use this for our child window. 717*cdf0e10cSrcweir maSize.setX(static_cast<sal_Int32>(rSizePixel.Width())); 718*cdf0e10cSrcweir maSize.setY(static_cast<sal_Int32>(rSizePixel.Height())); 719*cdf0e10cSrcweir 720*cdf0e10cSrcweir // let the child window cover the same size as the parent window. 721*cdf0e10cSrcweir mpWindow->SetPosSizePixel(0,0,maSize.getX(),maSize.getY()); 722*cdf0e10cSrcweir 723*cdf0e10cSrcweir // TODO(F2): since we would like to share precious hardware 724*cdf0e10cSrcweir // resources, the direct3d9 object should be global. each new 725*cdf0e10cSrcweir // request for a canvas should only create a new swapchain. 726*cdf0e10cSrcweir mpDirect3D9 = COMReference<IDirect3D9>( 727*cdf0e10cSrcweir Direct3DCreate9(D3D_SDK_VERSION)); 728*cdf0e10cSrcweir if(!mpDirect3D9.is()) 729*cdf0e10cSrcweir return false; 730*cdf0e10cSrcweir 731*cdf0e10cSrcweir // create a device from the direct3d9 object. 732*cdf0e10cSrcweir if(!(createDevice())) 733*cdf0e10cSrcweir return false; 734*cdf0e10cSrcweir 735*cdf0e10cSrcweir mpWindow->Show(); 736*cdf0e10cSrcweir 737*cdf0e10cSrcweir return true; 738*cdf0e10cSrcweir } 739*cdf0e10cSrcweir 740*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 741*cdf0e10cSrcweir // DXRenderModule::verifyDevice 742*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 743*cdf0e10cSrcweir 744*cdf0e10cSrcweir bool DXRenderModule::verifyDevice( const UINT nAdapter ) 745*cdf0e10cSrcweir { 746*cdf0e10cSrcweir ENSURE_OR_THROW( mpDirect3D9.is(), 747*cdf0e10cSrcweir "DXRenderModule::verifyDevice() No valid device." ); 748*cdf0e10cSrcweir 749*cdf0e10cSrcweir // ask direct3d9 about the capabilities of hardware devices on a specific adapter. 750*cdf0e10cSrcweir // here we decide if the underlying hardware of the machine 'is good enough'. 751*cdf0e10cSrcweir // since we only need a tiny little fraction of what could be used, this 752*cdf0e10cSrcweir // is basically a no-op. 753*cdf0e10cSrcweir D3DCAPS9 aCaps; 754*cdf0e10cSrcweir if(FAILED(mpDirect3D9->GetDeviceCaps(nAdapter,D3DDEVTYPE_HAL,&aCaps))) 755*cdf0e10cSrcweir return false; 756*cdf0e10cSrcweir if(!(aCaps.MaxTextureWidth)) 757*cdf0e10cSrcweir return false; 758*cdf0e10cSrcweir if(!(aCaps.MaxTextureHeight)) 759*cdf0e10cSrcweir return false; 760*cdf0e10cSrcweir maPageSize = ::basegfx::B2IVector(aCaps.MaxTextureWidth,aCaps.MaxTextureHeight); 761*cdf0e10cSrcweir 762*cdf0e10cSrcweir // check device against white & blacklist entries 763*cdf0e10cSrcweir D3DADAPTER_IDENTIFIER9 aIdent; 764*cdf0e10cSrcweir if(FAILED(mpDirect3D9->GetAdapterIdentifier(nAdapter,0,&aIdent))) 765*cdf0e10cSrcweir return false; 766*cdf0e10cSrcweir 767*cdf0e10cSrcweir DXCanvasItem aConfigItem; 768*cdf0e10cSrcweir DXCanvasItem::DeviceInfo aInfo; 769*cdf0e10cSrcweir aInfo.nVendorId = aIdent.VendorId; 770*cdf0e10cSrcweir aInfo.nDeviceId = aIdent.DeviceId; 771*cdf0e10cSrcweir aInfo.nDeviceSubSysId = aIdent.SubSysId; 772*cdf0e10cSrcweir aInfo.nDeviceRevision = aIdent.Revision; 773*cdf0e10cSrcweir 774*cdf0e10cSrcweir aInfo.nDriverId = HIWORD(aIdent.DriverVersion.HighPart); 775*cdf0e10cSrcweir aInfo.nDriverVersion = LOWORD(aIdent.DriverVersion.HighPart); 776*cdf0e10cSrcweir aInfo.nDriverSubVersion = HIWORD(aIdent.DriverVersion.LowPart); 777*cdf0e10cSrcweir aInfo.nDriverBuildId = LOWORD(aIdent.DriverVersion.LowPart); 778*cdf0e10cSrcweir 779*cdf0e10cSrcweir if( !aConfigItem.isDeviceUsable(aInfo) ) 780*cdf0e10cSrcweir return false; 781*cdf0e10cSrcweir 782*cdf0e10cSrcweir if( aConfigItem.isBlacklistCurrentDevice() ) 783*cdf0e10cSrcweir { 784*cdf0e10cSrcweir aConfigItem.blacklistDevice(aInfo); 785*cdf0e10cSrcweir return false; 786*cdf0e10cSrcweir } 787*cdf0e10cSrcweir 788*cdf0e10cSrcweir aConfigItem.adaptMaxTextureSize(maPageSize); 789*cdf0e10cSrcweir 790*cdf0e10cSrcweir mbCanUseDynamicTextures = (aCaps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) != 0; 791*cdf0e10cSrcweir 792*cdf0e10cSrcweir return true; 793*cdf0e10cSrcweir } 794*cdf0e10cSrcweir 795*cdf0e10cSrcweir 796*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 797*cdf0e10cSrcweir // DXRenderModule::createDevice 798*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 799*cdf0e10cSrcweir 800*cdf0e10cSrcweir bool DXRenderModule::createDevice() 801*cdf0e10cSrcweir { 802*cdf0e10cSrcweir // we expect that the caller provides us with a valid HWND 803*cdf0e10cSrcweir ENSURE_OR_THROW( IsWindow(mhWnd), 804*cdf0e10cSrcweir "DXRenderModule::createDevice() No valid HWND given." ); 805*cdf0e10cSrcweir 806*cdf0e10cSrcweir // we expect that the caller already created the direct3d9 object. 807*cdf0e10cSrcweir ENSURE_OR_THROW( mpDirect3D9.is(), 808*cdf0e10cSrcweir "DXRenderModule::createDevice() no direct3d?." ); 809*cdf0e10cSrcweir 810*cdf0e10cSrcweir // find the adapter identifier from the window. 811*cdf0e10cSrcweir const UINT aAdapter(getAdapterFromWindow()); 812*cdf0e10cSrcweir if(aAdapter == static_cast<UINT>(-1)) 813*cdf0e10cSrcweir return false; 814*cdf0e10cSrcweir 815*cdf0e10cSrcweir // verify that device possibly works 816*cdf0e10cSrcweir if( !verifyDevice(aAdapter) ) 817*cdf0e10cSrcweir return false; 818*cdf0e10cSrcweir 819*cdf0e10cSrcweir // query the display mode from the selected adapter. 820*cdf0e10cSrcweir // we'll later request the backbuffer format to be same 821*cdf0e10cSrcweir // same as the display format. 822*cdf0e10cSrcweir D3DDISPLAYMODE d3ddm; 823*cdf0e10cSrcweir mpDirect3D9->GetAdapterDisplayMode(aAdapter,&d3ddm); 824*cdf0e10cSrcweir 825*cdf0e10cSrcweir // we need to use D3DSWAPEFFECT_COPY here since the canvas-api has 826*cdf0e10cSrcweir // basically nothing to do with efficient resource handling. it tries 827*cdf0e10cSrcweir // to avoid drawing whenevery possible, which is simply not the most 828*cdf0e10cSrcweir // efficient way we could leverage the hardware in this case. it would 829*cdf0e10cSrcweir // be far better to redraw the backbuffer each time we would like to 830*cdf0e10cSrcweir // display the content of the backbuffer, but we need to face reality 831*cdf0e10cSrcweir // here and follow how the canvas was designed. 832*cdf0e10cSrcweir 833*cdf0e10cSrcweir // Strictly speaking, we don't need a full screen worth of 834*cdf0e10cSrcweir // backbuffer here. We could also scale dynamically with 835*cdf0e10cSrcweir // the current window size, but this will make it 836*cdf0e10cSrcweir // necessary to temporarily have two buffers while copying 837*cdf0e10cSrcweir // from the old to the new one. What's more, at the time 838*cdf0e10cSrcweir // we need a larger buffer, DX might not have sufficient 839*cdf0e10cSrcweir // resources available, and we're then left with too small 840*cdf0e10cSrcweir // a back buffer, and no way of falling back to a 841*cdf0e10cSrcweir // different canvas implementation. 842*cdf0e10cSrcweir ZeroMemory( &mad3dpp, sizeof(mad3dpp) ); 843*cdf0e10cSrcweir mad3dpp.BackBufferWidth = std::max(sal_Int32(maSize.getX()), 844*cdf0e10cSrcweir sal_Int32(d3ddm.Width)); 845*cdf0e10cSrcweir mad3dpp.BackBufferHeight = std::max(sal_Int32(maSize.getY()), 846*cdf0e10cSrcweir sal_Int32(d3ddm.Height)); 847*cdf0e10cSrcweir mad3dpp.BackBufferCount = 1; 848*cdf0e10cSrcweir mad3dpp.Windowed = TRUE; 849*cdf0e10cSrcweir mad3dpp.SwapEffect = D3DSWAPEFFECT_COPY; 850*cdf0e10cSrcweir mad3dpp.BackBufferFormat = d3ddm.Format; 851*cdf0e10cSrcweir mad3dpp.EnableAutoDepthStencil = FALSE; 852*cdf0e10cSrcweir mad3dpp.hDeviceWindow = mhWnd; 853*cdf0e10cSrcweir mad3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; 854*cdf0e10cSrcweir 855*cdf0e10cSrcweir // now create the device, first try hardware vertex processing, 856*cdf0e10cSrcweir // then software vertex processing. if both queries fail, we give up 857*cdf0e10cSrcweir // and indicate failure. 858*cdf0e10cSrcweir IDirect3DDevice9 *pDevice(NULL); 859*cdf0e10cSrcweir if(FAILED(mpDirect3D9->CreateDevice(aAdapter, 860*cdf0e10cSrcweir D3DDEVTYPE_HAL, 861*cdf0e10cSrcweir mhWnd, 862*cdf0e10cSrcweir D3DCREATE_HARDWARE_VERTEXPROCESSING| 863*cdf0e10cSrcweir D3DCREATE_MULTITHREADED|D3DCREATE_FPU_PRESERVE, 864*cdf0e10cSrcweir &mad3dpp, 865*cdf0e10cSrcweir &pDevice))) 866*cdf0e10cSrcweir if(FAILED(mpDirect3D9->CreateDevice(aAdapter, 867*cdf0e10cSrcweir D3DDEVTYPE_HAL, 868*cdf0e10cSrcweir mhWnd, 869*cdf0e10cSrcweir D3DCREATE_SOFTWARE_VERTEXPROCESSING| 870*cdf0e10cSrcweir D3DCREATE_MULTITHREADED|D3DCREATE_FPU_PRESERVE, 871*cdf0e10cSrcweir &mad3dpp, 872*cdf0e10cSrcweir &pDevice))) 873*cdf0e10cSrcweir return false; 874*cdf0e10cSrcweir 875*cdf0e10cSrcweir // got it, store it in a safe place... 876*cdf0e10cSrcweir mpDevice=COMReference<IDirect3DDevice9>(pDevice); 877*cdf0e10cSrcweir 878*cdf0e10cSrcweir // After CreateDevice, the first swap chain already exists, so just get it... 879*cdf0e10cSrcweir IDirect3DSwapChain9 *pSwapChain(NULL); 880*cdf0e10cSrcweir pDevice->GetSwapChain(0,&pSwapChain); 881*cdf0e10cSrcweir mpSwapChain=COMReference<IDirect3DSwapChain9>(pSwapChain); 882*cdf0e10cSrcweir if( !mpSwapChain.is() ) 883*cdf0e10cSrcweir return false; 884*cdf0e10cSrcweir 885*cdf0e10cSrcweir // clear the render target [which is the backbuffer in this case]. 886*cdf0e10cSrcweir // we are forced to do this once, and furthermore right now. 887*cdf0e10cSrcweir // please note that this is only possible since we created the 888*cdf0e10cSrcweir // backbuffer with copy semantics [the content is preserved after 889*cdf0e10cSrcweir // calls to Present()], which is an unnecessarily expensive operation. 890*cdf0e10cSrcweir LPDIRECT3DSURFACE9 pBackBuffer = NULL; 891*cdf0e10cSrcweir mpSwapChain->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pBackBuffer); 892*cdf0e10cSrcweir mpDevice->SetRenderTarget( 0, pBackBuffer ); 893*cdf0e10cSrcweir mpDevice->Clear(0,NULL,D3DCLEAR_TARGET,0,1.0f,0L); 894*cdf0e10cSrcweir pBackBuffer->Release(); 895*cdf0e10cSrcweir 896*cdf0e10cSrcweir return true; 897*cdf0e10cSrcweir } 898*cdf0e10cSrcweir 899*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 900*cdf0e10cSrcweir // DXRenderModule::createSystemMemorySurface 901*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 902*cdf0e10cSrcweir 903*cdf0e10cSrcweir COMReference<IDirect3DSurface9> DXRenderModule::createSystemMemorySurface( const ::basegfx::B2IVector& rSize ) 904*cdf0e10cSrcweir { 905*cdf0e10cSrcweir if(isDisposed()) 906*cdf0e10cSrcweir return COMReference<IDirect3DSurface9>(NULL); 907*cdf0e10cSrcweir 908*cdf0e10cSrcweir // please note that D3DFMT_X8R8G8B8 is the only format we're 909*cdf0e10cSrcweir // able to choose here, since GetDC() doesn't support any 910*cdf0e10cSrcweir // other 32bit-format. 911*cdf0e10cSrcweir IDirect3DSurface9 *pSurface(NULL); 912*cdf0e10cSrcweir if( FAILED(mpDevice->CreateOffscreenPlainSurface( 913*cdf0e10cSrcweir rSize.getX(), 914*cdf0e10cSrcweir rSize.getY(), 915*cdf0e10cSrcweir D3DFMT_X8R8G8B8, 916*cdf0e10cSrcweir D3DPOOL_SYSTEMMEM, 917*cdf0e10cSrcweir &pSurface, 918*cdf0e10cSrcweir NULL)) ) 919*cdf0e10cSrcweir { 920*cdf0e10cSrcweir throw lang::NoSupportException( 921*cdf0e10cSrcweir ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 922*cdf0e10cSrcweir "Could not create offscreen surface - out of mem!") ),NULL); 923*cdf0e10cSrcweir } 924*cdf0e10cSrcweir 925*cdf0e10cSrcweir return COMReference<IDirect3DSurface9>(pSurface); 926*cdf0e10cSrcweir } 927*cdf0e10cSrcweir 928*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 929*cdf0e10cSrcweir // DXRenderModule::flip 930*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 931*cdf0e10cSrcweir 932*cdf0e10cSrcweir bool DXRenderModule::flip( const ::basegfx::B2IRectangle& rUpdateArea, 933*cdf0e10cSrcweir const ::basegfx::B2IRectangle& /*rCurrWindowArea*/ ) 934*cdf0e10cSrcweir { 935*cdf0e10cSrcweir // TODO(P2): get rid of those fine-grained locking 936*cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 937*cdf0e10cSrcweir 938*cdf0e10cSrcweir if(isDisposed() || !mpSwapChain.is()) 939*cdf0e10cSrcweir return false; 940*cdf0e10cSrcweir 941*cdf0e10cSrcweir flushVertexCache(); 942*cdf0e10cSrcweir 943*cdf0e10cSrcweir // TODO(P2): Might be faster to actually pass update area here 944*cdf0e10cSrcweir RECT aRect = 945*cdf0e10cSrcweir { 946*cdf0e10cSrcweir rUpdateArea.getMinX(), 947*cdf0e10cSrcweir rUpdateArea.getMinY(), 948*cdf0e10cSrcweir rUpdateArea.getMaxX(), 949*cdf0e10cSrcweir rUpdateArea.getMaxY() 950*cdf0e10cSrcweir }; 951*cdf0e10cSrcweir HRESULT hr(mpSwapChain->Present(&aRect,&aRect,NULL,NULL,0)); 952*cdf0e10cSrcweir if(FAILED(hr)) 953*cdf0e10cSrcweir { 954*cdf0e10cSrcweir if(hr != D3DERR_DEVICELOST) 955*cdf0e10cSrcweir return false; 956*cdf0e10cSrcweir 957*cdf0e10cSrcweir // interestingly enough, sometimes the Reset() below 958*cdf0e10cSrcweir // *still* causes DeviceLost errors. So, cycle until 959*cdf0e10cSrcweir // DX was kind enough to really reset the device... 960*cdf0e10cSrcweir do 961*cdf0e10cSrcweir { 962*cdf0e10cSrcweir mpVertexBuffer.reset(); 963*cdf0e10cSrcweir hr = mpDevice->Reset(&mad3dpp); 964*cdf0e10cSrcweir if(SUCCEEDED(hr)) 965*cdf0e10cSrcweir { 966*cdf0e10cSrcweir IDirect3DVertexBuffer9 *pVB(NULL); 967*cdf0e10cSrcweir DWORD aFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1); 968*cdf0e10cSrcweir if( FAILED(mpDevice->CreateVertexBuffer(sizeof(dxvertex)*maNumVertices, 969*cdf0e10cSrcweir D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, 970*cdf0e10cSrcweir aFVF, 971*cdf0e10cSrcweir D3DPOOL_DEFAULT, 972*cdf0e10cSrcweir &pVB, 973*cdf0e10cSrcweir NULL)) ) 974*cdf0e10cSrcweir { 975*cdf0e10cSrcweir throw lang::NoSupportException( 976*cdf0e10cSrcweir ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 977*cdf0e10cSrcweir "Could not create DirectX device - out of memory!")),NULL); 978*cdf0e10cSrcweir } 979*cdf0e10cSrcweir mpVertexBuffer=COMReference<IDirect3DVertexBuffer9>(pVB); 980*cdf0e10cSrcweir 981*cdf0e10cSrcweir // retry after the restore 982*cdf0e10cSrcweir if(SUCCEEDED(mpSwapChain->Present(&aRect,&aRect,NULL,NULL,0))) 983*cdf0e10cSrcweir return true; 984*cdf0e10cSrcweir } 985*cdf0e10cSrcweir 986*cdf0e10cSrcweir TimeValue aTimeout; 987*cdf0e10cSrcweir aTimeout.Seconds=1; 988*cdf0e10cSrcweir aTimeout.Nanosec=0; 989*cdf0e10cSrcweir osl_waitThread(&aTimeout); 990*cdf0e10cSrcweir } 991*cdf0e10cSrcweir while(hr == D3DERR_DEVICELOST); 992*cdf0e10cSrcweir 993*cdf0e10cSrcweir return false; 994*cdf0e10cSrcweir } 995*cdf0e10cSrcweir 996*cdf0e10cSrcweir return true; 997*cdf0e10cSrcweir } 998*cdf0e10cSrcweir 999*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1000*cdf0e10cSrcweir // DXRenderModule::screenShot 1001*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1002*cdf0e10cSrcweir 1003*cdf0e10cSrcweir void DXRenderModule::screenShot() 1004*cdf0e10cSrcweir { 1005*cdf0e10cSrcweir } 1006*cdf0e10cSrcweir 1007*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1008*cdf0e10cSrcweir // DXRenderModule::resize 1009*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1010*cdf0e10cSrcweir 1011*cdf0e10cSrcweir void DXRenderModule::resize( const ::basegfx::B2IRange& rect ) 1012*cdf0e10cSrcweir { 1013*cdf0e10cSrcweir // TODO(P2): get rid of those fine-grained locking 1014*cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 1015*cdf0e10cSrcweir 1016*cdf0e10cSrcweir if(isDisposed()) 1017*cdf0e10cSrcweir return; 1018*cdf0e10cSrcweir 1019*cdf0e10cSrcweir // don't do anything if the size didn't change. 1020*cdf0e10cSrcweir if(maSize.getX() == static_cast<sal_Int32>(rect.getWidth()) && 1021*cdf0e10cSrcweir maSize.getY() == static_cast<sal_Int32>(rect.getHeight())) 1022*cdf0e10cSrcweir return; 1023*cdf0e10cSrcweir 1024*cdf0e10cSrcweir // TODO(Q2): use numeric cast to prevent overflow 1025*cdf0e10cSrcweir maSize.setX(static_cast<sal_Int32>(rect.getWidth())); 1026*cdf0e10cSrcweir maSize.setY(static_cast<sal_Int32>(rect.getHeight())); 1027*cdf0e10cSrcweir 1028*cdf0e10cSrcweir mpWindow->SetPosSizePixel(0,0,maSize.getX(),maSize.getY()); 1029*cdf0e10cSrcweir 1030*cdf0e10cSrcweir // resize back buffer, if necessary 1031*cdf0e10cSrcweir // ------------------------------------------------------------- 1032*cdf0e10cSrcweir 1033*cdf0e10cSrcweir // don't attempt to create anything if the 1034*cdf0e10cSrcweir // requested size is NULL. 1035*cdf0e10cSrcweir if(!(maSize.getX())) 1036*cdf0e10cSrcweir return; 1037*cdf0e10cSrcweir if(!(maSize.getY())) 1038*cdf0e10cSrcweir return; 1039*cdf0e10cSrcweir 1040*cdf0e10cSrcweir // backbuffer too small (might happen, if window is 1041*cdf0e10cSrcweir // maximized across multiple monitors) 1042*cdf0e10cSrcweir if( sal_Int32(mad3dpp.BackBufferWidth) < maSize.getX() || 1043*cdf0e10cSrcweir sal_Int32(mad3dpp.BackBufferHeight) < maSize.getY() ) 1044*cdf0e10cSrcweir { 1045*cdf0e10cSrcweir mad3dpp.BackBufferWidth = maSize.getX(); 1046*cdf0e10cSrcweir mad3dpp.BackBufferHeight = maSize.getY(); 1047*cdf0e10cSrcweir 1048*cdf0e10cSrcweir // clear before, save resources 1049*cdf0e10cSrcweir mpSwapChain.reset(); 1050*cdf0e10cSrcweir 1051*cdf0e10cSrcweir IDirect3DSwapChain9 *pSwapChain(NULL); 1052*cdf0e10cSrcweir if(FAILED(mpDevice->CreateAdditionalSwapChain(&mad3dpp,&pSwapChain))) 1053*cdf0e10cSrcweir return; 1054*cdf0e10cSrcweir mpSwapChain=COMReference<IDirect3DSwapChain9>(pSwapChain); 1055*cdf0e10cSrcweir 1056*cdf0e10cSrcweir // clear the render target [which is the backbuffer in this case]. 1057*cdf0e10cSrcweir // we are forced to do this once, and furthermore right now. 1058*cdf0e10cSrcweir // please note that this is only possible since we created the 1059*cdf0e10cSrcweir // backbuffer with copy semantics [the content is preserved after 1060*cdf0e10cSrcweir // calls to Present()], which is an unnecessarily expensive operation. 1061*cdf0e10cSrcweir LPDIRECT3DSURFACE9 pBackBuffer = NULL; 1062*cdf0e10cSrcweir mpSwapChain->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pBackBuffer); 1063*cdf0e10cSrcweir mpDevice->SetRenderTarget( 0, pBackBuffer ); 1064*cdf0e10cSrcweir mpDevice->Clear(0,NULL,D3DCLEAR_TARGET,0,1.0f,0L); 1065*cdf0e10cSrcweir pBackBuffer->Release(); 1066*cdf0e10cSrcweir } 1067*cdf0e10cSrcweir } 1068*cdf0e10cSrcweir 1069*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1070*cdf0e10cSrcweir // DXRenderModule::getPageSize 1071*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1072*cdf0e10cSrcweir 1073*cdf0e10cSrcweir ::basegfx::B2IVector DXRenderModule::getPageSize() 1074*cdf0e10cSrcweir { 1075*cdf0e10cSrcweir // TODO(P2): get rid of those fine-grained locking 1076*cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 1077*cdf0e10cSrcweir return maPageSize; 1078*cdf0e10cSrcweir } 1079*cdf0e10cSrcweir 1080*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1081*cdf0e10cSrcweir // DXRenderModule::createSurface 1082*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1083*cdf0e10cSrcweir 1084*cdf0e10cSrcweir ::canvas::ISurfaceSharedPtr DXRenderModule::createSurface( const ::basegfx::B2IVector& surfaceSize ) 1085*cdf0e10cSrcweir { 1086*cdf0e10cSrcweir // TODO(P2): get rid of those fine-grained locking 1087*cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 1088*cdf0e10cSrcweir 1089*cdf0e10cSrcweir if(isDisposed()) 1090*cdf0e10cSrcweir return ::canvas::ISurfaceSharedPtr(); 1091*cdf0e10cSrcweir 1092*cdf0e10cSrcweir const ::basegfx::B2IVector& rPageSize( getPageSize() ); 1093*cdf0e10cSrcweir ::basegfx::B2ISize aSize(surfaceSize); 1094*cdf0e10cSrcweir if(!(aSize.getX())) 1095*cdf0e10cSrcweir aSize.setX(rPageSize.getX()); 1096*cdf0e10cSrcweir if(!(aSize.getY())) 1097*cdf0e10cSrcweir aSize.setY(rPageSize.getY()); 1098*cdf0e10cSrcweir 1099*cdf0e10cSrcweir if(mpTexture.use_count() == 1) 1100*cdf0e10cSrcweir return mpTexture; 1101*cdf0e10cSrcweir 1102*cdf0e10cSrcweir return ::canvas::ISurfaceSharedPtr( new DXSurface(*this,aSize) ); 1103*cdf0e10cSrcweir } 1104*cdf0e10cSrcweir 1105*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1106*cdf0e10cSrcweir // DXRenderModule::beginPrimitive 1107*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1108*cdf0e10cSrcweir 1109*cdf0e10cSrcweir void DXRenderModule::beginPrimitive( PrimitiveType eType ) 1110*cdf0e10cSrcweir { 1111*cdf0e10cSrcweir // TODO(P2): get rid of those fine-grained locking 1112*cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 1113*cdf0e10cSrcweir 1114*cdf0e10cSrcweir if(isDisposed()) 1115*cdf0e10cSrcweir return; 1116*cdf0e10cSrcweir 1117*cdf0e10cSrcweir ENSURE_OR_THROW( !mnBeginSceneCount, 1118*cdf0e10cSrcweir "DXRenderModule::beginPrimitive(): nested call" ); 1119*cdf0e10cSrcweir 1120*cdf0e10cSrcweir ++mnBeginSceneCount; 1121*cdf0e10cSrcweir meType=eType; 1122*cdf0e10cSrcweir mnCount=0; 1123*cdf0e10cSrcweir } 1124*cdf0e10cSrcweir 1125*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1126*cdf0e10cSrcweir // DXRenderModule::endPrimitive 1127*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1128*cdf0e10cSrcweir 1129*cdf0e10cSrcweir void DXRenderModule::endPrimitive() 1130*cdf0e10cSrcweir { 1131*cdf0e10cSrcweir // TODO(P2): get rid of those fine-grained locking 1132*cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 1133*cdf0e10cSrcweir 1134*cdf0e10cSrcweir if(isDisposed()) 1135*cdf0e10cSrcweir return; 1136*cdf0e10cSrcweir 1137*cdf0e10cSrcweir --mnBeginSceneCount; 1138*cdf0e10cSrcweir meType=PRIMITIVE_TYPE_UNKNOWN; 1139*cdf0e10cSrcweir mnCount=0; 1140*cdf0e10cSrcweir } 1141*cdf0e10cSrcweir 1142*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1143*cdf0e10cSrcweir // DXRenderModule::pushVertex 1144*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1145*cdf0e10cSrcweir 1146*cdf0e10cSrcweir void DXRenderModule::pushVertex( const ::canvas::Vertex& vertex ) 1147*cdf0e10cSrcweir { 1148*cdf0e10cSrcweir // TODO(P2): get rid of those fine-grained locking 1149*cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 1150*cdf0e10cSrcweir 1151*cdf0e10cSrcweir if(isDisposed()) 1152*cdf0e10cSrcweir return; 1153*cdf0e10cSrcweir 1154*cdf0e10cSrcweir switch(meType) 1155*cdf0e10cSrcweir { 1156*cdf0e10cSrcweir case PRIMITIVE_TYPE_TRIANGLE: 1157*cdf0e10cSrcweir { 1158*cdf0e10cSrcweir maVertexCache.push_back(vertex); 1159*cdf0e10cSrcweir ++mnCount; 1160*cdf0e10cSrcweir mnCount &= 3; 1161*cdf0e10cSrcweir break; 1162*cdf0e10cSrcweir } 1163*cdf0e10cSrcweir 1164*cdf0e10cSrcweir case PRIMITIVE_TYPE_QUAD: 1165*cdf0e10cSrcweir { 1166*cdf0e10cSrcweir if(mnCount == 3) 1167*cdf0e10cSrcweir { 1168*cdf0e10cSrcweir const std::size_t size(maVertexCache.size()); 1169*cdf0e10cSrcweir ::canvas::Vertex v0(maVertexCache[size-1]); 1170*cdf0e10cSrcweir ::canvas::Vertex v2(maVertexCache[size-3]); 1171*cdf0e10cSrcweir maVertexCache.push_back(v0); 1172*cdf0e10cSrcweir maVertexCache.push_back(vertex); 1173*cdf0e10cSrcweir maVertexCache.push_back(v2); 1174*cdf0e10cSrcweir mnCount=0; 1175*cdf0e10cSrcweir } 1176*cdf0e10cSrcweir else 1177*cdf0e10cSrcweir { 1178*cdf0e10cSrcweir maVertexCache.push_back(vertex); 1179*cdf0e10cSrcweir ++mnCount; 1180*cdf0e10cSrcweir } 1181*cdf0e10cSrcweir break; 1182*cdf0e10cSrcweir } 1183*cdf0e10cSrcweir 1184*cdf0e10cSrcweir default: 1185*cdf0e10cSrcweir OSL_ENSURE(false, 1186*cdf0e10cSrcweir "DXRenderModule::pushVertex(): unexpected primitive type"); 1187*cdf0e10cSrcweir break; 1188*cdf0e10cSrcweir } 1189*cdf0e10cSrcweir } 1190*cdf0e10cSrcweir 1191*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1192*cdf0e10cSrcweir // DXRenderModule::isError 1193*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1194*cdf0e10cSrcweir 1195*cdf0e10cSrcweir bool DXRenderModule::isError() 1196*cdf0e10cSrcweir { 1197*cdf0e10cSrcweir // TODO(P2): get rid of those fine-grained locking 1198*cdf0e10cSrcweir ::osl::MutexGuard aGuard( maMutex ); 1199*cdf0e10cSrcweir 1200*cdf0e10cSrcweir return mbError; 1201*cdf0e10cSrcweir } 1202*cdf0e10cSrcweir 1203*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1204*cdf0e10cSrcweir // DXRenderModule::getAdapterFromWindow 1205*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1206*cdf0e10cSrcweir 1207*cdf0e10cSrcweir UINT DXRenderModule::getAdapterFromWindow() 1208*cdf0e10cSrcweir { 1209*cdf0e10cSrcweir HMONITOR hMonitor(aMonitorSupport.MonitorFromWindow(mhWnd)); 1210*cdf0e10cSrcweir UINT aAdapterCount(mpDirect3D9->GetAdapterCount()); 1211*cdf0e10cSrcweir for(UINT i=0; i<aAdapterCount; ++i) 1212*cdf0e10cSrcweir if(hMonitor == mpDirect3D9->GetAdapterMonitor(i)) 1213*cdf0e10cSrcweir return i; 1214*cdf0e10cSrcweir return static_cast<UINT>(-1); 1215*cdf0e10cSrcweir } 1216*cdf0e10cSrcweir 1217*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1218*cdf0e10cSrcweir // DXRenderModule::commitVertexCache 1219*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1220*cdf0e10cSrcweir 1221*cdf0e10cSrcweir void DXRenderModule::commitVertexCache() 1222*cdf0e10cSrcweir { 1223*cdf0e10cSrcweir if(maReadIndex != maWriteIndex) 1224*cdf0e10cSrcweir { 1225*cdf0e10cSrcweir const std::size_t nVertexStride = sizeof(dxvertex); 1226*cdf0e10cSrcweir const unsigned int nNumVertices = maWriteIndex-maReadIndex; 1227*cdf0e10cSrcweir const unsigned int nNumPrimitives = nNumVertices / 3; 1228*cdf0e10cSrcweir 1229*cdf0e10cSrcweir if(FAILED(mpDevice->SetStreamSource(0,mpVertexBuffer.get(),0,nVertexStride))) 1230*cdf0e10cSrcweir return; 1231*cdf0e10cSrcweir 1232*cdf0e10cSrcweir if(FAILED(mpDevice->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1))) 1233*cdf0e10cSrcweir return; 1234*cdf0e10cSrcweir 1235*cdf0e10cSrcweir if(FAILED(mpDevice->BeginScene())) 1236*cdf0e10cSrcweir return; 1237*cdf0e10cSrcweir 1238*cdf0e10cSrcweir mbError |= FAILED(mpDevice->DrawPrimitive(D3DPT_TRIANGLELIST,maReadIndex,nNumPrimitives)); 1239*cdf0e10cSrcweir mbError |= FAILED(mpDevice->EndScene()); 1240*cdf0e10cSrcweir 1241*cdf0e10cSrcweir maReadIndex += nNumVertices; 1242*cdf0e10cSrcweir } 1243*cdf0e10cSrcweir } 1244*cdf0e10cSrcweir 1245*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1246*cdf0e10cSrcweir // DXRenderModule::flushVertexCache 1247*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1248*cdf0e10cSrcweir 1249*cdf0e10cSrcweir void DXRenderModule::flushVertexCache() 1250*cdf0e10cSrcweir { 1251*cdf0e10cSrcweir if(!(maVertexCache.size())) 1252*cdf0e10cSrcweir return; 1253*cdf0e10cSrcweir 1254*cdf0e10cSrcweir mbError=true; 1255*cdf0e10cSrcweir 1256*cdf0e10cSrcweir if( FAILED(mpDevice->SetRenderState(D3DRS_LIGHTING,FALSE))) 1257*cdf0e10cSrcweir return; 1258*cdf0e10cSrcweir 1259*cdf0e10cSrcweir // enable texture alpha blending 1260*cdf0e10cSrcweir if( FAILED(mpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE))) 1261*cdf0e10cSrcweir return; 1262*cdf0e10cSrcweir 1263*cdf0e10cSrcweir mpDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); 1264*cdf0e10cSrcweir mpDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); 1265*cdf0e10cSrcweir mpDevice->SetSamplerState(0,D3DSAMP_ADDRESSU ,D3DTADDRESS_CLAMP ); 1266*cdf0e10cSrcweir mpDevice->SetSamplerState(0,D3DSAMP_ADDRESSV ,D3DTADDRESS_CLAMP ); 1267*cdf0e10cSrcweir 1268*cdf0e10cSrcweir // configure the fixed-function pipeline. 1269*cdf0e10cSrcweir // the only 'feature' we need here is to modulate the alpha-channels 1270*cdf0e10cSrcweir // from the texture and the interpolated diffuse color. the result 1271*cdf0e10cSrcweir // will then be blended with the backbuffer. 1272*cdf0e10cSrcweir // fragment color = texture color * diffuse.alpha. 1273*cdf0e10cSrcweir mpDevice->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_MODULATE); 1274*cdf0e10cSrcweir mpDevice->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE); 1275*cdf0e10cSrcweir mpDevice->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE); 1276*cdf0e10cSrcweir 1277*cdf0e10cSrcweir // normal combination of object... 1278*cdf0e10cSrcweir if( FAILED(mpDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA)) ) 1279*cdf0e10cSrcweir return; 1280*cdf0e10cSrcweir 1281*cdf0e10cSrcweir // ..and background color 1282*cdf0e10cSrcweir if( FAILED(mpDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA)) ) 1283*cdf0e10cSrcweir return; 1284*cdf0e10cSrcweir 1285*cdf0e10cSrcweir // disable backface culling; this enables us to mirror sprites 1286*cdf0e10cSrcweir // by simply reverting the triangles, which, with enabled 1287*cdf0e10cSrcweir // culling, would be invisible otherwise 1288*cdf0e10cSrcweir if( FAILED(mpDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE)) ) 1289*cdf0e10cSrcweir return; 1290*cdf0e10cSrcweir 1291*cdf0e10cSrcweir mbError=false; 1292*cdf0e10cSrcweir 1293*cdf0e10cSrcweir std::size_t nSize(maVertexCache.size()); 1294*cdf0e10cSrcweir const std::size_t nVertexStride = sizeof(dxvertex); 1295*cdf0e10cSrcweir 1296*cdf0e10cSrcweir const ::basegfx::B2IVector aPageSize(getPageSize()); 1297*cdf0e10cSrcweir const float nHalfPixelSizeX(0.5f/aPageSize.getX()); 1298*cdf0e10cSrcweir const float nHalfPixelSizeY(0.5f/aPageSize.getY()); 1299*cdf0e10cSrcweir vertexCache_t::const_iterator it(maVertexCache.begin()); 1300*cdf0e10cSrcweir 1301*cdf0e10cSrcweir while( nSize ) 1302*cdf0e10cSrcweir { 1303*cdf0e10cSrcweir DWORD dwLockFlags(D3DLOCK_NOOVERWRITE); 1304*cdf0e10cSrcweir 1305*cdf0e10cSrcweir // Check to see if there's space for the current set of 1306*cdf0e10cSrcweir // vertices in the buffer. 1307*cdf0e10cSrcweir if( maNumVertices - maWriteIndex < nSize ) 1308*cdf0e10cSrcweir { 1309*cdf0e10cSrcweir commitVertexCache(); 1310*cdf0e10cSrcweir dwLockFlags = D3DLOCK_DISCARD; 1311*cdf0e10cSrcweir maWriteIndex = 0; 1312*cdf0e10cSrcweir maReadIndex = 0; 1313*cdf0e10cSrcweir } 1314*cdf0e10cSrcweir 1315*cdf0e10cSrcweir dxvertex *vertices(NULL); 1316*cdf0e10cSrcweir const std::size_t nNumVertices( 1317*cdf0e10cSrcweir std::min(maNumVertices - maWriteIndex, 1318*cdf0e10cSrcweir nSize)); 1319*cdf0e10cSrcweir if(FAILED(mpVertexBuffer->Lock(maWriteIndex*nVertexStride, 1320*cdf0e10cSrcweir nNumVertices*nVertexStride, 1321*cdf0e10cSrcweir (void **)&vertices, 1322*cdf0e10cSrcweir dwLockFlags))) 1323*cdf0e10cSrcweir return; 1324*cdf0e10cSrcweir 1325*cdf0e10cSrcweir std::size_t nIndex(0); 1326*cdf0e10cSrcweir while( nIndex < nNumVertices ) 1327*cdf0e10cSrcweir { 1328*cdf0e10cSrcweir dxvertex &dest = vertices[nIndex++]; 1329*cdf0e10cSrcweir dest.x=it->x; 1330*cdf0e10cSrcweir dest.y=it->y; 1331*cdf0e10cSrcweir dest.z=it->z; 1332*cdf0e10cSrcweir dest.rhw=1; 1333*cdf0e10cSrcweir const sal_uInt32 alpha(static_cast<sal_uInt32>(it->a*255.0f)); 1334*cdf0e10cSrcweir dest.diffuse=D3DCOLOR_ARGB(alpha,255,255,255); 1335*cdf0e10cSrcweir dest.u=static_cast<float>(it->u + nHalfPixelSizeX); 1336*cdf0e10cSrcweir dest.v=static_cast<float>(it->v + nHalfPixelSizeY); 1337*cdf0e10cSrcweir ++it; 1338*cdf0e10cSrcweir } 1339*cdf0e10cSrcweir 1340*cdf0e10cSrcweir mpVertexBuffer->Unlock(); 1341*cdf0e10cSrcweir 1342*cdf0e10cSrcweir // Advance to the next position in the vertex buffer. 1343*cdf0e10cSrcweir maWriteIndex += nNumVertices; 1344*cdf0e10cSrcweir nSize -= nNumVertices; 1345*cdf0e10cSrcweir 1346*cdf0e10cSrcweir commitVertexCache(); 1347*cdf0e10cSrcweir } 1348*cdf0e10cSrcweir 1349*cdf0e10cSrcweir maVertexCache.clear(); 1350*cdf0e10cSrcweir } 1351*cdf0e10cSrcweir } 1352*cdf0e10cSrcweir 1353*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1354*cdf0e10cSrcweir // createRenderModule 1355*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////////// 1356*cdf0e10cSrcweir 1357*cdf0e10cSrcweir IDXRenderModuleSharedPtr createRenderModule( const ::Window& rParent ) 1358*cdf0e10cSrcweir { 1359*cdf0e10cSrcweir return IDXRenderModuleSharedPtr( new DXRenderModule(rParent) ); 1360*cdf0e10cSrcweir } 1361*cdf0e10cSrcweir } 1362*cdf0e10cSrcweir 1363*cdf0e10cSrcweir #endif 1364