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