xref: /AOO41X/main/canvas/source/directx/dx_9rm.cxx (revision 79aad27f7f29270c03e208e3d687e8e3850af11d)
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