xref: /AOO41X/main/canvas/source/directx/dx_5rm.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_canvas.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #if DIRECTX_VERSION < 0x0900
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir // Nvidia GeForce Go 6800 crashes with a bluescreen if we take the
34*cdf0e10cSrcweir // maximum texture size, which would be twice as large. this behaviors
35*cdf0e10cSrcweir // has only been observed on directx5.
36*cdf0e10cSrcweir // This value is simply the maximum size for textures we request from
37*cdf0e10cSrcweir // the system, it has absolutely nothing to do with the size of primitives
38*cdf0e10cSrcweir // we're able to render, both concepts are totally independent from each other.
39*cdf0e10cSrcweir #define MAX_TEXTURE_SIZE (2048)
40*cdf0e10cSrcweir #define MIN_TEXTURE_SIZE (32)
41*cdf0e10cSrcweir //#define FAKE_MAX_NUMBER_TEXTURES (2)
42*cdf0e10cSrcweir //#define FAKE_MAX_TEXTURE_SIZE (512)
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////////
45*cdf0e10cSrcweir // includes
46*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////////
47*cdf0e10cSrcweir #include <vcl/syschild.hxx>
48*cdf0e10cSrcweir #include <vcl/window.hxx>
49*cdf0e10cSrcweir #include <canvas/debug.hxx>
50*cdf0e10cSrcweir #include <canvas/verbosetrace.hxx>
51*cdf0e10cSrcweir #include <canvas/elapsedtime.hxx>
52*cdf0e10cSrcweir #include <canvas/canvastools.hxx>
53*cdf0e10cSrcweir #include <canvas/rendering/icolorbuffer.hxx>
54*cdf0e10cSrcweir #include <canvas/rendering/isurface.hxx>
55*cdf0e10cSrcweir #include <canvas/rendering/irendermodule.hxx>
56*cdf0e10cSrcweir #include <tools/diagnose_ex.h>
57*cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
58*cdf0e10cSrcweir #include <basegfx/vector/b2dsize.hxx>
59*cdf0e10cSrcweir #include <basegfx/vector/b2isize.hxx>
60*cdf0e10cSrcweir #include <basegfx/point/b2ipoint.hxx>
61*cdf0e10cSrcweir #include <basegfx/range/b2irectangle.hxx>
62*cdf0e10cSrcweir #include <boost/scoped_ptr.hpp>
63*cdf0e10cSrcweir #include <com/sun/star/lang/NoSupportException.hpp>
64*cdf0e10cSrcweir 
65*cdf0e10cSrcweir #define COMPILE_MULTIMON_STUBS
66*cdf0e10cSrcweir 
67*cdf0e10cSrcweir #include "dx_rendermodule.hxx"
68*cdf0e10cSrcweir #include "dx_surfacegraphics.hxx"
69*cdf0e10cSrcweir #include <vcl/sysdata.hxx>
70*cdf0e10cSrcweir 
71*cdf0e10cSrcweir #undef WB_LEFT
72*cdf0e10cSrcweir #undef WB_RIGHT
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir #include "dx_impltools.hxx"
75*cdf0e10cSrcweir #include <malloc.h>
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir #if defined(DX_DEBUG_IMAGES)
78*cdf0e10cSrcweir # if OSL_DEBUG_LEVEL > 0
79*cdf0e10cSrcweir #  include <imdebug.h>
80*cdf0e10cSrcweir #  undef min
81*cdf0e10cSrcweir #  undef max
82*cdf0e10cSrcweir # endif
83*cdf0e10cSrcweir #endif
84*cdf0e10cSrcweir 
85*cdf0e10cSrcweir #undef COMPILE_MULTIMON_STUBS
86*cdf0e10cSrcweir 
87*cdf0e10cSrcweir #include <stdio.h>
88*cdf0e10cSrcweir 
89*cdf0e10cSrcweir #define MONITOR_DEFAULTTONULL       0x00000000
90*cdf0e10cSrcweir #define MONITOR_DEFAULTTOPRIMARY    0x00000001
91*cdf0e10cSrcweir #define MONITOR_DEFAULTTONEAREST    0x00000002
92*cdf0e10cSrcweir 
93*cdf0e10cSrcweir using namespace ::com::sun::star;
94*cdf0e10cSrcweir 
95*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////////
96*cdf0e10cSrcweir // 'dxcanvas' namespace
97*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////////
98*cdf0e10cSrcweir 
99*cdf0e10cSrcweir namespace dxcanvas
100*cdf0e10cSrcweir {
101*cdf0e10cSrcweir 	namespace
102*cdf0e10cSrcweir 	{
103*cdf0e10cSrcweir         bool doBlit( const ::basegfx::B2IPoint& rDestPos,
104*cdf0e10cSrcweir                      IDirectDrawSurface&        rOutSurface,
105*cdf0e10cSrcweir                      const ::basegfx::B2IRange& rSourceArea,
106*cdf0e10cSrcweir                      IDirectDrawSurface&        rSourceSurface,
107*cdf0e10cSrcweir                      DDBLTFX*                   pBltFx,
108*cdf0e10cSrcweir                      bool                       bForceSoftware )
109*cdf0e10cSrcweir         {
110*cdf0e10cSrcweir             if( !bForceSoftware )
111*cdf0e10cSrcweir             {
112*cdf0e10cSrcweir                 // blit surface to backbuffer
113*cdf0e10cSrcweir                 RECT aOutRect =
114*cdf0e10cSrcweir                     {
115*cdf0e10cSrcweir                         rDestPos.getX(),
116*cdf0e10cSrcweir                         rDestPos.getY(),
117*cdf0e10cSrcweir                         rDestPos.getX() + static_cast<sal_Int32>(rSourceArea.getWidth()),
118*cdf0e10cSrcweir                         rDestPos.getY() + static_cast<sal_Int32>(rSourceArea.getHeight()),
119*cdf0e10cSrcweir                     };
120*cdf0e10cSrcweir                 RECT aSourceRect =
121*cdf0e10cSrcweir                     {
122*cdf0e10cSrcweir                         rSourceArea.getMinX(),
123*cdf0e10cSrcweir                         rSourceArea.getMinY(),
124*cdf0e10cSrcweir                         rSourceArea.getMaxX(),
125*cdf0e10cSrcweir                         rSourceArea.getMaxY()
126*cdf0e10cSrcweir                     };
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir                 if( SUCCEEDED(rOutSurface.Blt( &aOutRect,
129*cdf0e10cSrcweir                                                &rSourceSurface,
130*cdf0e10cSrcweir                                                &aSourceRect,
131*cdf0e10cSrcweir                                                DDBLT_WAIT,
132*cdf0e10cSrcweir                                                pBltFx )) )
133*cdf0e10cSrcweir                 {
134*cdf0e10cSrcweir                     return true;
135*cdf0e10cSrcweir                 }
136*cdf0e10cSrcweir             }
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir             // failed, or forced to use SW copy. attempt manual copy.
139*cdf0e10cSrcweir             bool bResult = false;
140*cdf0e10cSrcweir 
141*cdf0e10cSrcweir             // lock source surface
142*cdf0e10cSrcweir             DDSURFACEDESC aDescSrc;
143*cdf0e10cSrcweir             rtl_fillMemory(&aDescSrc,sizeof(DDSURFACEDESC),0);
144*cdf0e10cSrcweir             aDescSrc.dwSize = sizeof(DDSURFACEDESC);
145*cdf0e10cSrcweir             const DWORD dwSrcFlags = DDLOCK_NOSYSLOCK|
146*cdf0e10cSrcweir                 DDLOCK_SURFACEMEMORYPTR|
147*cdf0e10cSrcweir                 DDLOCK_WAIT|
148*cdf0e10cSrcweir                 DDLOCK_READONLY;
149*cdf0e10cSrcweir             if(SUCCEEDED(rSourceSurface.Lock(NULL,
150*cdf0e10cSrcweir                                              &aDescSrc,
151*cdf0e10cSrcweir                                              dwSrcFlags,
152*cdf0e10cSrcweir                                              NULL)))
153*cdf0e10cSrcweir             {
154*cdf0e10cSrcweir                 // lock destination surface
155*cdf0e10cSrcweir                 DDSURFACEDESC aDescDst;
156*cdf0e10cSrcweir                 rtl_fillMemory(&aDescDst,sizeof(DDSURFACEDESC),0);
157*cdf0e10cSrcweir                 aDescDst.dwSize = sizeof(DDSURFACEDESC);
158*cdf0e10cSrcweir                 const DWORD dwDstFlags = DDLOCK_NOSYSLOCK|
159*cdf0e10cSrcweir                     DDLOCK_SURFACEMEMORYPTR|
160*cdf0e10cSrcweir                     DDLOCK_WAIT|
161*cdf0e10cSrcweir                     DDLOCK_WRITEONLY;
162*cdf0e10cSrcweir                 if(SUCCEEDED(rOutSurface.Lock(NULL,
163*cdf0e10cSrcweir                                               &aDescDst,
164*cdf0e10cSrcweir                                               dwDstFlags,
165*cdf0e10cSrcweir                                               NULL)))
166*cdf0e10cSrcweir                 {
167*cdf0e10cSrcweir                     sal_uInt32 nSrcFormat;
168*cdf0e10cSrcweir                     nSrcFormat  = ::canvas::tools::bitcount32(aDescSrc.ddpfPixelFormat.dwRGBAlphaBitMask)<<12;
169*cdf0e10cSrcweir                     nSrcFormat |= ::canvas::tools::bitcount32(aDescSrc.ddpfPixelFormat.dwRBitMask)<<8;
170*cdf0e10cSrcweir                     nSrcFormat |= ::canvas::tools::bitcount32(aDescSrc.ddpfPixelFormat.dwGBitMask)<<4;
171*cdf0e10cSrcweir                     nSrcFormat |= ::canvas::tools::bitcount32(aDescSrc.ddpfPixelFormat.dwBBitMask);
172*cdf0e10cSrcweir 
173*cdf0e10cSrcweir                     sal_uInt32 nDstFormat;
174*cdf0e10cSrcweir                     nDstFormat  = ::canvas::tools::bitcount32(aDescDst.ddpfPixelFormat.dwRGBAlphaBitMask)<<12;
175*cdf0e10cSrcweir                     nDstFormat |= ::canvas::tools::bitcount32(aDescDst.ddpfPixelFormat.dwRBitMask)<<8;
176*cdf0e10cSrcweir                     nDstFormat |= ::canvas::tools::bitcount32(aDescDst.ddpfPixelFormat.dwGBitMask)<<4;
177*cdf0e10cSrcweir                     nDstFormat |= ::canvas::tools::bitcount32(aDescDst.ddpfPixelFormat.dwBBitMask);
178*cdf0e10cSrcweir 
179*cdf0e10cSrcweir                     // TODO(E1): Use numeric_cast to catch overflow here
180*cdf0e10cSrcweir                     const sal_uInt32 nWidth( static_cast<sal_uInt32>(
181*cdf0e10cSrcweir                                                    rSourceArea.getWidth() ) );
182*cdf0e10cSrcweir                     const sal_uInt32 nHeight( static_cast<sal_uInt32>(
183*cdf0e10cSrcweir                                                     rSourceArea.getHeight() ) );
184*cdf0e10cSrcweir 
185*cdf0e10cSrcweir                     if((nSrcFormat == 0x8888) && (nDstFormat == 0x0565))
186*cdf0e10cSrcweir                     {
187*cdf0e10cSrcweir                         // medium range 8888 to 0565 pixel format conversion.
188*cdf0e10cSrcweir                         bResult = true;
189*cdf0e10cSrcweir                         sal_uInt8 *pSrcSurface = (sal_uInt8 *)aDescSrc.lpSurface +
190*cdf0e10cSrcweir                             rSourceArea.getMinY()*aDescSrc.lPitch +
191*cdf0e10cSrcweir                             (rSourceArea.getMinX()<<2);
192*cdf0e10cSrcweir                         sal_uInt8 *pDstSurface = (sal_uInt8 *)aDescDst.lpSurface +
193*cdf0e10cSrcweir                             rDestPos.getY()*aDescDst.lPitch +
194*cdf0e10cSrcweir                             (rDestPos.getX()<<1);
195*cdf0e10cSrcweir                         for(sal_uInt32 y=0; y<nHeight; ++y)
196*cdf0e10cSrcweir                         {
197*cdf0e10cSrcweir                             sal_uInt32 *pSrcScanline = (sal_uInt32 *)pSrcSurface;
198*cdf0e10cSrcweir                             sal_uInt16 *pDstScanline = (sal_uInt16 *)pDstSurface;
199*cdf0e10cSrcweir                             for(sal_uInt32 x=0; x<nWidth; ++x)
200*cdf0e10cSrcweir                             {
201*cdf0e10cSrcweir                                 sal_uInt32 srcPixel = *pSrcScanline++;
202*cdf0e10cSrcweir                                 sal_uInt16 dstPixel;
203*cdf0e10cSrcweir                                 dstPixel  = (sal_uInt16)((srcPixel & 0x0000F8) >> 3);
204*cdf0e10cSrcweir                                 dstPixel |= (srcPixel & 0x00FC00) >> 5;
205*cdf0e10cSrcweir                                 dstPixel |= (srcPixel & 0xF80000) >> 8;
206*cdf0e10cSrcweir                                 *pDstScanline++ = dstPixel;
207*cdf0e10cSrcweir                             }
208*cdf0e10cSrcweir                             pSrcSurface += aDescSrc.lPitch;
209*cdf0e10cSrcweir                             pDstSurface += aDescDst.lPitch;
210*cdf0e10cSrcweir                         }
211*cdf0e10cSrcweir                     }
212*cdf0e10cSrcweir                     else if((nSrcFormat == 0x8888) && (nDstFormat == 0x0888))
213*cdf0e10cSrcweir                     {
214*cdf0e10cSrcweir                         // medium range 8888 to 0888 pixel format conversion.
215*cdf0e10cSrcweir                         bResult = true;
216*cdf0e10cSrcweir                         sal_uInt8 *pSrcSurface = (sal_uInt8 *)aDescSrc.lpSurface +
217*cdf0e10cSrcweir                             rSourceArea.getMinY()*aDescSrc.lPitch +
218*cdf0e10cSrcweir                             (rSourceArea.getMinX()<<2);
219*cdf0e10cSrcweir                         sal_uInt8 *pDstSurface = (sal_uInt8 *)aDescDst.lpSurface +
220*cdf0e10cSrcweir                             rDestPos.getY()*aDescDst.lPitch +
221*cdf0e10cSrcweir                             (rDestPos.getX()<<2);
222*cdf0e10cSrcweir                         for(sal_uInt32 y=0; y<nHeight; ++y)
223*cdf0e10cSrcweir                         {
224*cdf0e10cSrcweir                             sal_uInt32 *pSrcScanline = (sal_uInt32 *)pSrcSurface;
225*cdf0e10cSrcweir                             sal_uInt16 *pDstScanline = (sal_uInt16 *)pDstSurface;
226*cdf0e10cSrcweir                             for(sal_uInt32 x=0; x<nWidth; ++x)
227*cdf0e10cSrcweir                             {
228*cdf0e10cSrcweir                                 *pDstScanline++ = (sal_uInt16)*pSrcScanline++;
229*cdf0e10cSrcweir                             }
230*cdf0e10cSrcweir                             pSrcSurface += aDescSrc.lPitch;
231*cdf0e10cSrcweir                             pDstSurface += aDescDst.lPitch;
232*cdf0e10cSrcweir                         }
233*cdf0e10cSrcweir                     }
234*cdf0e10cSrcweir                     else if((nSrcFormat == 0x8888) && (nDstFormat == 0x1555))
235*cdf0e10cSrcweir                     {
236*cdf0e10cSrcweir                         // medium range 8888 to 1555 pixel format conversion.
237*cdf0e10cSrcweir                         bResult = true;
238*cdf0e10cSrcweir                         sal_uInt8 *pSrcSurface = (sal_uInt8 *)aDescSrc.lpSurface +
239*cdf0e10cSrcweir                             rSourceArea.getMinY()*aDescSrc.lPitch +
240*cdf0e10cSrcweir                             (rSourceArea.getMinX()<<2);
241*cdf0e10cSrcweir                         sal_uInt8 *pDstSurface = (sal_uInt8 *)aDescDst.lpSurface +
242*cdf0e10cSrcweir                             rDestPos.getY()*aDescDst.lPitch +
243*cdf0e10cSrcweir                             (rDestPos.getX()<<1);
244*cdf0e10cSrcweir                         for(sal_uInt32 y=0; y<nHeight; ++y)
245*cdf0e10cSrcweir                         {
246*cdf0e10cSrcweir                             sal_uInt32 *pSrcScanline = (sal_uInt32*)pSrcSurface;
247*cdf0e10cSrcweir                             sal_uInt16 *pDstScanline = (sal_uInt16 *)pDstSurface;
248*cdf0e10cSrcweir                             for(sal_uInt32 x=0; x<nWidth; ++x)
249*cdf0e10cSrcweir                             {
250*cdf0e10cSrcweir                                 sal_uInt32 srcPixel = *pSrcScanline++;
251*cdf0e10cSrcweir                                 sal_uInt16 dstPixel;
252*cdf0e10cSrcweir                                 dstPixel  = (sal_uInt16)((srcPixel & 0x000000F8) >> 3);
253*cdf0e10cSrcweir                                 dstPixel |= (srcPixel & 0x0000F800) >> 6;
254*cdf0e10cSrcweir                                 dstPixel |= (srcPixel & 0x00F80000) >> 9;
255*cdf0e10cSrcweir                                 dstPixel |= (srcPixel & 0x80000000) >> 16;
256*cdf0e10cSrcweir                                 *pDstScanline++ = dstPixel;
257*cdf0e10cSrcweir                             }
258*cdf0e10cSrcweir                             pSrcSurface += aDescSrc.lPitch;
259*cdf0e10cSrcweir                             pDstSurface += aDescDst.lPitch;
260*cdf0e10cSrcweir                         }
261*cdf0e10cSrcweir                     }
262*cdf0e10cSrcweir 
263*cdf0e10cSrcweir                     // unlock destination surface
264*cdf0e10cSrcweir                     rOutSurface.Unlock(NULL);
265*cdf0e10cSrcweir                 }
266*cdf0e10cSrcweir 
267*cdf0e10cSrcweir                 // unlock source surface
268*cdf0e10cSrcweir                 rSourceSurface.Unlock(NULL);
269*cdf0e10cSrcweir             }
270*cdf0e10cSrcweir 
271*cdf0e10cSrcweir             return bResult;
272*cdf0e10cSrcweir         }
273*cdf0e10cSrcweir 
274*cdf0e10cSrcweir 		void dumpSurface( const COMReference<IDirectDrawSurface> &pSurface, const char *szFilename )
275*cdf0e10cSrcweir 		{
276*cdf0e10cSrcweir 			if(!(pSurface.get()))
277*cdf0e10cSrcweir 				return;
278*cdf0e10cSrcweir 
279*cdf0e10cSrcweir 			DDSURFACEDESC aSurfaceDesc;
280*cdf0e10cSrcweir 			rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 );
281*cdf0e10cSrcweir 			aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
282*cdf0e10cSrcweir 
283*cdf0e10cSrcweir 			if( FAILED(pSurface->Lock( NULL,
284*cdf0e10cSrcweir 										&aSurfaceDesc,
285*cdf0e10cSrcweir 										DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY,
286*cdf0e10cSrcweir 										NULL)) )
287*cdf0e10cSrcweir 				return;
288*cdf0e10cSrcweir 
289*cdf0e10cSrcweir 			const std::size_t dwBitmapSize(aSurfaceDesc.dwWidth*aSurfaceDesc.dwHeight*4);
290*cdf0e10cSrcweir 			sal_uInt8 *pBuffer = static_cast<sal_uInt8 *>(_alloca(dwBitmapSize));
291*cdf0e10cSrcweir 			if(pBuffer)
292*cdf0e10cSrcweir 			{
293*cdf0e10cSrcweir 				sal_uInt8 *pSource = reinterpret_cast<sal_uInt8 *>(aSurfaceDesc.lpSurface);
294*cdf0e10cSrcweir 				sal_uInt8 *pDest = reinterpret_cast<sal_uInt8 *>(pBuffer);
295*cdf0e10cSrcweir 				const std::size_t dwDestPitch(aSurfaceDesc.dwWidth<<2);
296*cdf0e10cSrcweir 				pDest += aSurfaceDesc.dwHeight*dwDestPitch;
297*cdf0e10cSrcweir 				for(sal_uInt32 y=0; y<aSurfaceDesc.dwHeight; ++y)
298*cdf0e10cSrcweir 				{
299*cdf0e10cSrcweir 					pDest -= dwDestPitch;
300*cdf0e10cSrcweir 					rtl_copyMemory( pDest, pSource, dwDestPitch );
301*cdf0e10cSrcweir 					pSource += aSurfaceDesc.lPitch;
302*cdf0e10cSrcweir 				}
303*cdf0e10cSrcweir 
304*cdf0e10cSrcweir 				if(FILE *fp = fopen(szFilename,"wb"))
305*cdf0e10cSrcweir 				{
306*cdf0e10cSrcweir 					BITMAPINFOHEADER bitmapInfo;
307*cdf0e10cSrcweir 
308*cdf0e10cSrcweir 					bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
309*cdf0e10cSrcweir 					bitmapInfo.biWidth = aSurfaceDesc.dwWidth;
310*cdf0e10cSrcweir 					bitmapInfo.biHeight = aSurfaceDesc.dwHeight;
311*cdf0e10cSrcweir 					bitmapInfo.biPlanes = 1;
312*cdf0e10cSrcweir 					bitmapInfo.biBitCount = 32;
313*cdf0e10cSrcweir 					bitmapInfo.biCompression = BI_RGB;
314*cdf0e10cSrcweir 					bitmapInfo.biSizeImage = 0;
315*cdf0e10cSrcweir 					bitmapInfo.biXPelsPerMeter = 0;
316*cdf0e10cSrcweir 					bitmapInfo.biYPelsPerMeter = 0;
317*cdf0e10cSrcweir 					bitmapInfo.biClrUsed = 0;
318*cdf0e10cSrcweir 					bitmapInfo.biClrImportant = 0;
319*cdf0e10cSrcweir 
320*cdf0e10cSrcweir 					const std::size_t dwFileSize(sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwBitmapSize);
321*cdf0e10cSrcweir 
322*cdf0e10cSrcweir 					BITMAPFILEHEADER header;
323*cdf0e10cSrcweir 					header.bfType = 'MB';
324*cdf0e10cSrcweir 					header.bfSize = dwFileSize;
325*cdf0e10cSrcweir 					header.bfReserved1 = 0;
326*cdf0e10cSrcweir 					header.bfReserved2 = 0;
327*cdf0e10cSrcweir 					header.bfOffBits = sizeof(BITMAPFILEHEADER) + bitmapInfo.biSize;
328*cdf0e10cSrcweir 
329*cdf0e10cSrcweir 					fwrite(&header,1,sizeof(BITMAPFILEHEADER),fp);
330*cdf0e10cSrcweir 					fwrite(&bitmapInfo,1,sizeof(BITMAPINFOHEADER),fp);
331*cdf0e10cSrcweir 					fwrite(pBuffer,1,dwBitmapSize,fp);
332*cdf0e10cSrcweir 
333*cdf0e10cSrcweir 					fclose(fp);
334*cdf0e10cSrcweir 				}
335*cdf0e10cSrcweir 			}
336*cdf0e10cSrcweir 
337*cdf0e10cSrcweir 			pSurface->Unlock(NULL);
338*cdf0e10cSrcweir 		}
339*cdf0e10cSrcweir 
340*cdf0e10cSrcweir 		void clearSurface( const COMReference<IDirectDrawSurface>& pSurface )
341*cdf0e10cSrcweir 		{
342*cdf0e10cSrcweir 			if(!(pSurface.is()))
343*cdf0e10cSrcweir 				return;
344*cdf0e10cSrcweir 
345*cdf0e10cSrcweir 			DDBLTFX aBltFx;
346*cdf0e10cSrcweir 
347*cdf0e10cSrcweir 			rtl_fillMemory( &aBltFx,
348*cdf0e10cSrcweir 							sizeof(DDBLTFX), 0 );
349*cdf0e10cSrcweir 			aBltFx.dwSize = sizeof(DDBLTFX);
350*cdf0e10cSrcweir 			aBltFx.dwFillColor = 0;
351*cdf0e10cSrcweir 
352*cdf0e10cSrcweir 			pSurface->Blt( NULL,
353*cdf0e10cSrcweir                            NULL,
354*cdf0e10cSrcweir                            NULL,
355*cdf0e10cSrcweir                            DDBLT_COLORFILL | DDBLT_WAIT,
356*cdf0e10cSrcweir                            &aBltFx );
357*cdf0e10cSrcweir 		}
358*cdf0e10cSrcweir 
359*cdf0e10cSrcweir 		// Define struct for MonitorEntry
360*cdf0e10cSrcweir 		struct MonitorEntry
361*cdf0e10cSrcweir 		{
362*cdf0e10cSrcweir  			GUID                 mnGUID;
363*cdf0e10cSrcweir  			HMONITOR             mhMonitor;
364*cdf0e10cSrcweir             MONITORINFO   maMonitorInfo;
365*cdf0e10cSrcweir 		};
366*cdf0e10cSrcweir 
367*cdf0e10cSrcweir 		// define type for MonitorList
368*cdf0e10cSrcweir         typedef ::std::vector< MonitorEntry > MonitorList;
369*cdf0e10cSrcweir 
370*cdf0e10cSrcweir  		// Win32 system callback for DirectDrawEnumerateExA call
371*cdf0e10cSrcweir  		BOOL WINAPI EnumerateExA_Callback( GUID FAR* lpGUID,
372*cdf0e10cSrcweir                                            LPSTR     /*lpDriverDescription*/,
373*cdf0e10cSrcweir                                            LPSTR     /*lpDriverName*/,
374*cdf0e10cSrcweir                                            LPVOID    lpContext,
375*cdf0e10cSrcweir                                            HMONITOR  hMonitor )
376*cdf0e10cSrcweir 		{
377*cdf0e10cSrcweir 			if(lpGUID)
378*cdf0e10cSrcweir 			{
379*cdf0e10cSrcweir  				MonitorList* pMonitorList = (MonitorList*)lpContext;
380*cdf0e10cSrcweir 				MonitorEntry aEntry;
381*cdf0e10cSrcweir 
382*cdf0e10cSrcweir  				aEntry.mnGUID = *lpGUID;
383*cdf0e10cSrcweir  				aEntry.mhMonitor = hMonitor;
384*cdf0e10cSrcweir                 aEntry.maMonitorInfo.cbSize = sizeof(MONITORINFO);
385*cdf0e10cSrcweir                 GetMonitorInfo( hMonitor,
386*cdf0e10cSrcweir                                 &aEntry.maMonitorInfo );
387*cdf0e10cSrcweir 
388*cdf0e10cSrcweir 				pMonitorList->push_back(aEntry);
389*cdf0e10cSrcweir 			}
390*cdf0e10cSrcweir 
391*cdf0e10cSrcweir 			return DDENUMRET_OK;
392*cdf0e10cSrcweir 		}
393*cdf0e10cSrcweir 
394*cdf0e10cSrcweir         void fillMonitorList( MonitorList& rMonitorList )
395*cdf0e10cSrcweir         {
396*cdf0e10cSrcweir             // Try to fill MonitorList. If neither lib or call to
397*cdf0e10cSrcweir             // DirectDrawEnumerateExA does not exist, it's an old
398*cdf0e10cSrcweir             // DX version (< 5.0), or system does not support
399*cdf0e10cSrcweir             // multiple monitors.
400*cdf0e10cSrcweir             HINSTANCE hInstance = LoadLibrary("ddraw.dll");
401*cdf0e10cSrcweir 
402*cdf0e10cSrcweir             if(hInstance)
403*cdf0e10cSrcweir             {
404*cdf0e10cSrcweir                 LPDIRECTDRAWENUMERATEEX lpDDEnumEx =
405*cdf0e10cSrcweir                     (LPDIRECTDRAWENUMERATEEX)GetProcAddress(hInstance,"DirectDrawEnumerateExA");
406*cdf0e10cSrcweir 
407*cdf0e10cSrcweir                 if(lpDDEnumEx)
408*cdf0e10cSrcweir                     lpDDEnumEx( (LPDDENUMCALLBACKEXA) EnumerateExA_Callback,
409*cdf0e10cSrcweir                                 &rMonitorList,
410*cdf0e10cSrcweir                                 DDENUM_ATTACHEDSECONDARYDEVICES );
411*cdf0e10cSrcweir 
412*cdf0e10cSrcweir                 FreeLibrary(hInstance);
413*cdf0e10cSrcweir             }
414*cdf0e10cSrcweir         }
415*cdf0e10cSrcweir 
416*cdf0e10cSrcweir         IDirectDraw2* createDirectDraw( const MonitorList& rMonitorList,
417*cdf0e10cSrcweir                                         MONITORINFO&       rMonitorInfo,
418*cdf0e10cSrcweir                                         HWND        renderWindow )
419*cdf0e10cSrcweir         {
420*cdf0e10cSrcweir  			GUID* gpSelectedDriverGUID = NULL;
421*cdf0e10cSrcweir 
422*cdf0e10cSrcweir             // if we have multiple monitors, choose a gpSelectedDriverGUID from monitor list
423*cdf0e10cSrcweir             HMONITOR hMonitor = MonitorFromWindow(renderWindow,
424*cdf0e10cSrcweir                                                   MONITOR_DEFAULTTONEAREST);
425*cdf0e10cSrcweir 
426*cdf0e10cSrcweir             MonitorList::const_iterator       aCurr = rMonitorList.begin();
427*cdf0e10cSrcweir             const MonitorList::const_iterator aEnd = rMonitorList.end();
428*cdf0e10cSrcweir             while( !gpSelectedDriverGUID && aCurr != aEnd )
429*cdf0e10cSrcweir             {
430*cdf0e10cSrcweir                 if(hMonitor == aCurr->mhMonitor)
431*cdf0e10cSrcweir                 {
432*cdf0e10cSrcweir                     // This is the monitor we are running on
433*cdf0e10cSrcweir                     gpSelectedDriverGUID = const_cast<GUID*>(&aCurr->mnGUID);
434*cdf0e10cSrcweir                     rMonitorInfo = aCurr->maMonitorInfo;
435*cdf0e10cSrcweir                 }
436*cdf0e10cSrcweir 
437*cdf0e10cSrcweir                 ++aCurr;
438*cdf0e10cSrcweir             }
439*cdf0e10cSrcweir 
440*cdf0e10cSrcweir             IDirectDraw* pDirectDraw;
441*cdf0e10cSrcweir             if( FAILED( DirectDrawCreate( gpSelectedDriverGUID, &pDirectDraw, NULL )))
442*cdf0e10cSrcweir                 return NULL;
443*cdf0e10cSrcweir 
444*cdf0e10cSrcweir             IDirectDraw2* pDirectDraw2;
445*cdf0e10cSrcweir             if( FAILED( pDirectDraw->QueryInterface( IID_IDirectDraw2, (LPVOID*)&pDirectDraw2 )))
446*cdf0e10cSrcweir                 return NULL;
447*cdf0e10cSrcweir 
448*cdf0e10cSrcweir 			// queryInterface bumped up the refcount, so release the
449*cdf0e10cSrcweir 			// reference to the original IDirectDraw interface.
450*cdf0e10cSrcweir 			pDirectDraw->Release();
451*cdf0e10cSrcweir 
452*cdf0e10cSrcweir             return pDirectDraw2;
453*cdf0e10cSrcweir         }
454*cdf0e10cSrcweir 
455*cdf0e10cSrcweir         HRESULT WINAPI EnumTextureFormatsCallback( LPDDSURFACEDESC 	pSurfaceDesc,
456*cdf0e10cSrcweir                                                    LPVOID			pContext		)
457*cdf0e10cSrcweir         {
458*cdf0e10cSrcweir             // dirty cast of given context back to result ModeSelectContext
459*cdf0e10cSrcweir             DDPIXELFORMAT* pResult = (DDPIXELFORMAT*)pContext;
460*cdf0e10cSrcweir 
461*cdf0e10cSrcweir             if( pResult == NULL || pSurfaceDesc == NULL )
462*cdf0e10cSrcweir                 return DDENUMRET_CANCEL;
463*cdf0e10cSrcweir 
464*cdf0e10cSrcweir             VERBOSE_TRACE( "EnumTextureFormatsCallback: advertised texture format has dwRGBBitCount %d, dwRBitMask %x, "
465*cdf0e10cSrcweir                            "dwGBitMask %x, dwBBitMask %x and dwRGBAlphaBitMask %x. The format uses %s alpha.",
466*cdf0e10cSrcweir                            pSurfaceDesc->ddpfPixelFormat.dwRGBBitCount,
467*cdf0e10cSrcweir                            pSurfaceDesc->ddpfPixelFormat.dwRBitMask,
468*cdf0e10cSrcweir                            pSurfaceDesc->ddpfPixelFormat.dwGBitMask,
469*cdf0e10cSrcweir                            pSurfaceDesc->ddpfPixelFormat.dwBBitMask,
470*cdf0e10cSrcweir                            pSurfaceDesc->ddpfPixelFormat.dwRGBAlphaBitMask,
471*cdf0e10cSrcweir                            pSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_ALPHAPREMULT ? "premultiplied" : "non-premultiplied" );
472*cdf0e10cSrcweir 
473*cdf0e10cSrcweir             // Only accept RGB surfaces with alpha channel
474*cdf0e10cSrcweir             if( (DDPF_ALPHAPIXELS | DDPF_RGB) ==
475*cdf0e10cSrcweir                 (pSurfaceDesc->ddpfPixelFormat.dwFlags & (DDPF_ALPHAPIXELS | DDPF_RGB)) )
476*cdf0e10cSrcweir             {
477*cdf0e10cSrcweir 				// ignore formats with the DDPF_ALPHAPREMULT flag
478*cdf0e10cSrcweir 				if(!(pSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_ALPHAPREMULT))
479*cdf0e10cSrcweir 				{
480*cdf0e10cSrcweir 					// take widest alpha channel available
481*cdf0e10cSrcweir 					if( pSurfaceDesc->ddpfPixelFormat.dwAlphaBitDepth > pResult->dwAlphaBitDepth )
482*cdf0e10cSrcweir 					{
483*cdf0e10cSrcweir 						// take new format
484*cdf0e10cSrcweir 						rtl_copyMemory( pResult, &pSurfaceDesc->ddpfPixelFormat, sizeof(DDPIXELFORMAT) );
485*cdf0e10cSrcweir 					}
486*cdf0e10cSrcweir 					else if( pSurfaceDesc->ddpfPixelFormat.dwAlphaBitDepth == pResult->dwAlphaBitDepth )
487*cdf0e10cSrcweir 					{
488*cdf0e10cSrcweir 						// tie-breaking: take highest bitcount
489*cdf0e10cSrcweir 						if( pSurfaceDesc->ddpfPixelFormat.dwRGBBitCount > pResult->dwRGBBitCount )
490*cdf0e10cSrcweir 						{
491*cdf0e10cSrcweir 							// take new format
492*cdf0e10cSrcweir 							rtl_copyMemory( pResult, &pSurfaceDesc->ddpfPixelFormat, sizeof(DDPIXELFORMAT) );
493*cdf0e10cSrcweir 						}
494*cdf0e10cSrcweir 					}
495*cdf0e10cSrcweir 				}
496*cdf0e10cSrcweir             }
497*cdf0e10cSrcweir 
498*cdf0e10cSrcweir             return DDENUMRET_OK;
499*cdf0e10cSrcweir         }
500*cdf0e10cSrcweir 
501*cdf0e10cSrcweir 		class DXRenderModule;
502*cdf0e10cSrcweir 
503*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
504*cdf0e10cSrcweir 		// DXSurface
505*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
506*cdf0e10cSrcweir 
507*cdf0e10cSrcweir 		/** ISurface implemenation.
508*cdf0e10cSrcweir 
509*cdf0e10cSrcweir 			@attention holds the DXRenderModule via non-refcounted
510*cdf0e10cSrcweir 			reference! This is safe with current state of affairs, since
511*cdf0e10cSrcweir 			the canvas::PageManager holds surface and render module via
512*cdf0e10cSrcweir 			shared_ptr (and makes sure all surfaces are deleted before its
513*cdf0e10cSrcweir 			render module member goes out of scope).
514*cdf0e10cSrcweir 		*/
515*cdf0e10cSrcweir 		class DXSurface : public canvas::ISurface
516*cdf0e10cSrcweir 		{
517*cdf0e10cSrcweir 		public:
518*cdf0e10cSrcweir 			DXSurface( DXRenderModule&           rRenderModule,
519*cdf0e10cSrcweir                        const ::basegfx::B2ISize& rSize );
520*cdf0e10cSrcweir 			~DXSurface();
521*cdf0e10cSrcweir 
522*cdf0e10cSrcweir 			virtual bool selectTexture();
523*cdf0e10cSrcweir 			virtual bool isValid();
524*cdf0e10cSrcweir 			virtual bool update( const ::basegfx::B2IPoint& rDestPos,
525*cdf0e10cSrcweir                                  const ::basegfx::B2IRange& rSourceRect,
526*cdf0e10cSrcweir                                  ::canvas::IColorBuffer&    rSource );
527*cdf0e10cSrcweir 			virtual ::basegfx::B2IVector getSize();
528*cdf0e10cSrcweir 
529*cdf0e10cSrcweir 		private:
530*cdf0e10cSrcweir 			/// Guard local methods against concurrent acces to RenderModule
531*cdf0e10cSrcweir 			class ImplRenderModuleGuard : private ::boost::noncopyable
532*cdf0e10cSrcweir 			{
533*cdf0e10cSrcweir 			public:
534*cdf0e10cSrcweir 				explicit inline ImplRenderModuleGuard( DXRenderModule& rRenderModule );
535*cdf0e10cSrcweir 				inline ~ImplRenderModuleGuard();
536*cdf0e10cSrcweir 
537*cdf0e10cSrcweir 			private:
538*cdf0e10cSrcweir 				DXRenderModule& mrRenderModule;
539*cdf0e10cSrcweir 			};
540*cdf0e10cSrcweir 
541*cdf0e10cSrcweir 			DXRenderModule&                         mrRenderModule;
542*cdf0e10cSrcweir 
543*cdf0e10cSrcweir 			COMReference<IDirectDrawSurface> mpSurface;
544*cdf0e10cSrcweir 			COMReference<IDirect3DTexture2>  mpTexture;
545*cdf0e10cSrcweir 
546*cdf0e10cSrcweir 			::basegfx::B2IVector maSize;
547*cdf0e10cSrcweir 		};
548*cdf0e10cSrcweir 
549*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
550*cdf0e10cSrcweir 		// DXRenderModule
551*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
552*cdf0e10cSrcweir 
553*cdf0e10cSrcweir 		/// Default implementation of IDXRenderModule
554*cdf0e10cSrcweir 		class DXRenderModule : public IDXRenderModule
555*cdf0e10cSrcweir 		{
556*cdf0e10cSrcweir         public:
557*cdf0e10cSrcweir             explicit DXRenderModule( const ::Window& rWindow );
558*cdf0e10cSrcweir 
559*cdf0e10cSrcweir             virtual void lock() const { maMutex.acquire(); }
560*cdf0e10cSrcweir             virtual void unlock() const { maMutex.release(); }
561*cdf0e10cSrcweir 
562*cdf0e10cSrcweir             virtual COMReference<IDirectDrawSurface>
563*cdf0e10cSrcweir                 createSystemMemorySurface( const ::basegfx::B2IVector& rSize );
564*cdf0e10cSrcweir 
565*cdf0e10cSrcweir             virtual bool flip( const ::basegfx::B2IRectangle& rUpdateArea,
566*cdf0e10cSrcweir                                const ::basegfx::B2IRectangle& rCurrWindowArea );
567*cdf0e10cSrcweir 
568*cdf0e10cSrcweir             virtual void resize( const ::basegfx::B2IRange& rect );
569*cdf0e10cSrcweir 			virtual HWND getHWND() const { return mhWnd; }
570*cdf0e10cSrcweir 			virtual void disposing();
571*cdf0e10cSrcweir 			virtual void screenShot();
572*cdf0e10cSrcweir             virtual ::basegfx::B2IVector getPageSize();
573*cdf0e10cSrcweir             virtual ::canvas::ISurfaceSharedPtr createSurface( const ::basegfx::B2IVector& surfaceSize );
574*cdf0e10cSrcweir             virtual void beginPrimitive( PrimitiveType eType );
575*cdf0e10cSrcweir             virtual void endPrimitive();
576*cdf0e10cSrcweir             virtual void pushVertex( const ::canvas::Vertex& vertex );
577*cdf0e10cSrcweir             virtual bool isError();
578*cdf0e10cSrcweir 
579*cdf0e10cSrcweir             const D3DDEVICEDESC&             getDeviceDesc() const { return maDeviceDesc; }
580*cdf0e10cSrcweir             const DDPIXELFORMAT&             getTextureFormat() const { return maTextureFormat; }
581*cdf0e10cSrcweir             COMReference<IDirectDraw2>       getDirectDraw() { return mpDirectDraw; }
582*cdf0e10cSrcweir             COMReference< IDirect3DDevice2 > getDevice() { return mpDirect3DDevice; }
583*cdf0e10cSrcweir 
584*cdf0e10cSrcweir             void flushVertexCache();
585*cdf0e10cSrcweir 
586*cdf0e10cSrcweir             struct ModeSelectContext
587*cdf0e10cSrcweir             {
588*cdf0e10cSrcweir                 DDSURFACEDESC selectedDesc;
589*cdf0e10cSrcweir                 ::basegfx::B2ISize	 requestedSize;
590*cdf0e10cSrcweir             };
591*cdf0e10cSrcweir 
592*cdf0e10cSrcweir             /** Query actual size of the device
593*cdf0e10cSrcweir 
594*cdf0e10cSrcweir                 This is especially interesting for fullscreen devices
595*cdf0e10cSrcweir             */
596*cdf0e10cSrcweir             ::basegfx::B2ISize getFramebufferSize() const;
597*cdf0e10cSrcweir 
598*cdf0e10cSrcweir             /** Query the amount of memory available for new surfaces
599*cdf0e10cSrcweir 
600*cdf0e10cSrcweir                 This might differ from getAvailableTextureMem()
601*cdf0e10cSrcweir                 @see getAvailableTextureMem()
602*cdf0e10cSrcweir 
603*cdf0e10cSrcweir                 @param bWithAGPMema
604*cdf0e10cSrcweir                 When true, returned value includes non-local,
605*cdf0e10cSrcweir                 i.e. AGP-able memory, too.
606*cdf0e10cSrcweir 
607*cdf0e10cSrcweir                 @return the amount of free surface mem
608*cdf0e10cSrcweir             */
609*cdf0e10cSrcweir             std::size_t	  getAvailableSurfaceMem( bool bWithAGPMem=true ) const;
610*cdf0e10cSrcweir 
611*cdf0e10cSrcweir             /** Query the amount of memory available for new textures
612*cdf0e10cSrcweir 
613*cdf0e10cSrcweir                 This might differ from getAvailableSurfaceMem()
614*cdf0e10cSrcweir                 @see getAvailableSurfaceMem()
615*cdf0e10cSrcweir 
616*cdf0e10cSrcweir                 @param bWithAGPMema
617*cdf0e10cSrcweir                 When true, returned value includes non-local,
618*cdf0e10cSrcweir                 i.e. AGP-able memory, too.
619*cdf0e10cSrcweir 
620*cdf0e10cSrcweir                 @return the amount of free texture mem
621*cdf0e10cSrcweir             */
622*cdf0e10cSrcweir             std::size_t     getAvailableTextureMem( bool bWithAGPMem=true ) const;
623*cdf0e10cSrcweir 
624*cdf0e10cSrcweir         private:
625*cdf0e10cSrcweir             bool queryCaps();
626*cdf0e10cSrcweir             bool validateCaps();
627*cdf0e10cSrcweir             bool setup3DDevice();
628*cdf0e10cSrcweir             unsigned int getDisplayFormat() const;
629*cdf0e10cSrcweir 
630*cdf0e10cSrcweir             void convert2Screen( ::basegfx::B2IPoint& io_rDestPos,
631*cdf0e10cSrcweir                                  ::basegfx::B2IRange& io_rDestArea );
632*cdf0e10cSrcweir 
633*cdf0e10cSrcweir             void renderInfoText( const ::rtl::OUString& rStr,
634*cdf0e10cSrcweir                                  const Gdiplus::PointF& rPos ) const;
635*cdf0e10cSrcweir             void renderFPSCounter() const;
636*cdf0e10cSrcweir             void renderMemAvailable() const;
637*cdf0e10cSrcweir 
638*cdf0e10cSrcweir             bool create( const ::Window& rWindow );
639*cdf0e10cSrcweir             bool validateMainSurfaces();
640*cdf0e10cSrcweir 
641*cdf0e10cSrcweir             /** This object represents the DirectX state machine.  In order
642*cdf0e10cSrcweir                 to serialize access to DirectX's global state, a global
643*cdf0e10cSrcweir                 mutex is required.
644*cdf0e10cSrcweir             */
645*cdf0e10cSrcweir             static ::osl::Mutex						maMutex;
646*cdf0e10cSrcweir 
647*cdf0e10cSrcweir             HWND                                    mhWnd;
648*cdf0e10cSrcweir 			::boost::scoped_ptr<SystemChildWindow>	mpWindow;
649*cdf0e10cSrcweir 			::basegfx::B2IVector					maSize;
650*cdf0e10cSrcweir 
651*cdf0e10cSrcweir             ModeSelectContext						maSelectedFullscreenMode;
652*cdf0e10cSrcweir             DDPIXELFORMAT                           maTextureFormat;
653*cdf0e10cSrcweir 
654*cdf0e10cSrcweir             MONITORINFO                             maMonitorInfo; // monitor info for mpDirectDraw's monitor
655*cdf0e10cSrcweir             COMReference<IDirectDraw2>              mpDirectDraw;
656*cdf0e10cSrcweir             COMReference<IDirectDrawSurface>        mpPrimarySurface;
657*cdf0e10cSrcweir             COMReference<IDirectDrawSurface>        mpBackBufferSurface;
658*cdf0e10cSrcweir 
659*cdf0e10cSrcweir             COMReference< IDirect3D2 >              mpDirect3D;
660*cdf0e10cSrcweir             COMReference< IDirect3DDevice2 >        mpDirect3DDevice;
661*cdf0e10cSrcweir 
662*cdf0e10cSrcweir             mutable ::canvas::tools::ElapsedTime	maLastUpdate;	// for the frame counter
663*cdf0e10cSrcweir 
664*cdf0e10cSrcweir             D3DDEVICEDESC                           maDeviceDesc;
665*cdf0e10cSrcweir 
666*cdf0e10cSrcweir             typedef std::vector<canvas::Vertex>	    vertexCache_t;
667*cdf0e10cSrcweir             vertexCache_t							maVertexCache;
668*cdf0e10cSrcweir             std::size_t								mnCount;
669*cdf0e10cSrcweir 
670*cdf0e10cSrcweir             int                                     mnBeginSceneCount;
671*cdf0e10cSrcweir 
672*cdf0e10cSrcweir             const bool								mbPageFlipping;
673*cdf0e10cSrcweir             bool 									mbHasNoTearingBlt;
674*cdf0e10cSrcweir             bool									mbError;
675*cdf0e10cSrcweir             PrimitiveType							meType;
676*cdf0e10cSrcweir 
677*cdf0e10cSrcweir 			::canvas::ISurfaceSharedPtr				mpTexture;
678*cdf0e10cSrcweir 			::basegfx::B2IVector					maPageSize;
679*cdf0e10cSrcweir 		};
680*cdf0e10cSrcweir 
681*cdf0e10cSrcweir 		::osl::Mutex DXRenderModule::maMutex;
682*cdf0e10cSrcweir 
683*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
684*cdf0e10cSrcweir 		// DXSurface::ImplRenderModuleGuard
685*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
686*cdf0e10cSrcweir 
687*cdf0e10cSrcweir 		inline DXSurface::ImplRenderModuleGuard::ImplRenderModuleGuard(
688*cdf0e10cSrcweir 			DXRenderModule& rRenderModule ) :
689*cdf0e10cSrcweir 			mrRenderModule( rRenderModule )
690*cdf0e10cSrcweir 		{
691*cdf0e10cSrcweir 			mrRenderModule.lock();
692*cdf0e10cSrcweir 		}
693*cdf0e10cSrcweir 
694*cdf0e10cSrcweir 		inline DXSurface::ImplRenderModuleGuard::~ImplRenderModuleGuard()
695*cdf0e10cSrcweir 		{
696*cdf0e10cSrcweir 			mrRenderModule.unlock();
697*cdf0e10cSrcweir 		}
698*cdf0e10cSrcweir 
699*cdf0e10cSrcweir #ifdef FAKE_MAX_NUMBER_TEXTURES
700*cdf0e10cSrcweir 		static sal_uInt32 gNumSurfaces = 0;
701*cdf0e10cSrcweir #endif
702*cdf0e10cSrcweir 
703*cdf0e10cSrcweir         void fillRect( sal_uInt32 *pDest,
704*cdf0e10cSrcweir                        sal_uInt32 dwWidth,
705*cdf0e10cSrcweir                        sal_uInt32 dwHeight,
706*cdf0e10cSrcweir                        sal_uInt32 dwPitch,
707*cdf0e10cSrcweir                        sal_uInt32 dwColor )
708*cdf0e10cSrcweir         {
709*cdf0e10cSrcweir             for(sal_uInt32 i=0; i<dwWidth; ++i)
710*cdf0e10cSrcweir             {
711*cdf0e10cSrcweir                 pDest[i]=dwColor;
712*cdf0e10cSrcweir                 pDest[((dwHeight-1)*dwPitch)+i]=dwColor;
713*cdf0e10cSrcweir             }
714*cdf0e10cSrcweir 
715*cdf0e10cSrcweir             for(sal_uInt32 j=0; j<dwHeight; ++j)
716*cdf0e10cSrcweir             {
717*cdf0e10cSrcweir                 pDest[0]=dwColor;
718*cdf0e10cSrcweir                 pDest[dwWidth-1]=dwColor;
719*cdf0e10cSrcweir                 pDest += dwPitch;
720*cdf0e10cSrcweir             }
721*cdf0e10cSrcweir         }
722*cdf0e10cSrcweir 
723*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
724*cdf0e10cSrcweir 		// DXSurface::DXSurface
725*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
726*cdf0e10cSrcweir 
727*cdf0e10cSrcweir 		DXSurface::DXSurface( DXRenderModule&           rRenderModule,
728*cdf0e10cSrcweir 							  const ::basegfx::B2ISize& rSize ) :
729*cdf0e10cSrcweir             mrRenderModule(rRenderModule),
730*cdf0e10cSrcweir             mpTexture(NULL),
731*cdf0e10cSrcweir             mpSurface(NULL),
732*cdf0e10cSrcweir 			maSize()
733*cdf0e10cSrcweir 		{
734*cdf0e10cSrcweir 			ImplRenderModuleGuard aGuard( mrRenderModule );
735*cdf0e10cSrcweir 
736*cdf0e10cSrcweir #ifdef FAKE_MAX_NUMBER_TEXTURES
737*cdf0e10cSrcweir 			++gNumSurfaces;
738*cdf0e10cSrcweir 			if(gNumSurfaces >= FAKE_MAX_NUMBER_TEXTURES)
739*cdf0e10cSrcweir 				return;
740*cdf0e10cSrcweir #endif
741*cdf0e10cSrcweir 
742*cdf0e10cSrcweir #ifdef FAKE_MAX_TEXTURE_SIZE
743*cdf0e10cSrcweir 			if(rSize.getX() > FAKE_MAX_TEXTURE_SIZE)
744*cdf0e10cSrcweir 				return;
745*cdf0e10cSrcweir 			if(rSize.getY() > FAKE_MAX_TEXTURE_SIZE)
746*cdf0e10cSrcweir 				return;
747*cdf0e10cSrcweir #endif
748*cdf0e10cSrcweir 
749*cdf0e10cSrcweir 			ENSURE_ARG_OR_THROW(rSize.getX() > 0 && rSize.getY() > 0,
750*cdf0e10cSrcweir 							"DXSurface::DXSurface(): request for zero-sized surface");
751*cdf0e10cSrcweir 
752*cdf0e10cSrcweir 			const D3DDEVICEDESC &deviceDesc = rRenderModule.getDeviceDesc();
753*cdf0e10cSrcweir 
754*cdf0e10cSrcweir 			DDSURFACEDESC aSurfaceDesc;
755*cdf0e10cSrcweir 			rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 );
756*cdf0e10cSrcweir 			aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
757*cdf0e10cSrcweir 			aSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
758*cdf0e10cSrcweir 			aSurfaceDesc.dwWidth = ::std::min(deviceDesc.dwMaxTextureWidth,::canvas::tools::nextPow2(rSize.getX()));
759*cdf0e10cSrcweir 			aSurfaceDesc.dwHeight = ::std::min(deviceDesc.dwMaxTextureHeight,::canvas::tools::nextPow2(rSize.getY()));
760*cdf0e10cSrcweir 			aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE |
761*cdf0e10cSrcweir 										  DDSCAPS_VIDEOMEMORY |
762*cdf0e10cSrcweir 										  DDSCAPS_LOCALVIDMEM;
763*cdf0e10cSrcweir 			rtl_copyMemory(&aSurfaceDesc.ddpfPixelFormat,&rRenderModule.getTextureFormat(),sizeof(DDPIXELFORMAT));
764*cdf0e10cSrcweir 
765*cdf0e10cSrcweir 	        IDirectDrawSurface *pSurface;
766*cdf0e10cSrcweir 			COMReference<IDirectDraw2> pDirectDraw(rRenderModule.getDirectDraw());
767*cdf0e10cSrcweir 			HRESULT hr = pDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
768*cdf0e10cSrcweir 			if(FAILED(hr))
769*cdf0e10cSrcweir 			{
770*cdf0e10cSrcweir 				// if the call failed due to 'out of videomemory',
771*cdf0e10cSrcweir 				// retry with request for AGP memory.
772*cdf0e10cSrcweir 				if(DDERR_OUTOFVIDEOMEMORY == hr)
773*cdf0e10cSrcweir 				{
774*cdf0e10cSrcweir 					aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE |
775*cdf0e10cSrcweir 												  DDSCAPS_VIDEOMEMORY |
776*cdf0e10cSrcweir 												  DDSCAPS_NONLOCALVIDMEM;
777*cdf0e10cSrcweir 					hr = pDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
778*cdf0e10cSrcweir 				}
779*cdf0e10cSrcweir 			}
780*cdf0e10cSrcweir 
781*cdf0e10cSrcweir 			if(SUCCEEDED(hr))
782*cdf0e10cSrcweir 			{
783*cdf0e10cSrcweir 				IDirect3DTexture2* pTexture;
784*cdf0e10cSrcweir 				if( FAILED(pSurface->QueryInterface(IID_IDirect3DTexture2, (LPVOID *)&pTexture)) )
785*cdf0e10cSrcweir 				{
786*cdf0e10cSrcweir 					pSurface->Release();
787*cdf0e10cSrcweir 					return;
788*cdf0e10cSrcweir 				}
789*cdf0e10cSrcweir 
790*cdf0e10cSrcweir 				maSize.setX(aSurfaceDesc.dwWidth);
791*cdf0e10cSrcweir 				maSize.setY(aSurfaceDesc.dwHeight);
792*cdf0e10cSrcweir 
793*cdf0e10cSrcweir 				mpSurface=COMReference<IDirectDrawSurface>(pSurface);
794*cdf0e10cSrcweir 				mpTexture=COMReference<IDirect3DTexture2>(pTexture);
795*cdf0e10cSrcweir 
796*cdf0e10cSrcweir 				// #122683# Clear texture, to avoid ugly artifacts at the
797*cdf0e10cSrcweir 				// border to invisible sprite areas (note that the textures
798*cdf0e10cSrcweir 				// are usually only partly utilized).
799*cdf0e10cSrcweir 				clearSurface( mpSurface );
800*cdf0e10cSrcweir 			}
801*cdf0e10cSrcweir 		}
802*cdf0e10cSrcweir 
803*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
804*cdf0e10cSrcweir 		// DXSurface::~DXSurface
805*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
806*cdf0e10cSrcweir 
807*cdf0e10cSrcweir 		DXSurface::~DXSurface()
808*cdf0e10cSrcweir 		{
809*cdf0e10cSrcweir 			ImplRenderModuleGuard aGuard( mrRenderModule );
810*cdf0e10cSrcweir 
811*cdf0e10cSrcweir #ifdef FAKE_MAX_NUMBER_TEXTURES
812*cdf0e10cSrcweir 			gNumSurfaces--;
813*cdf0e10cSrcweir #endif
814*cdf0e10cSrcweir 		}
815*cdf0e10cSrcweir 
816*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
817*cdf0e10cSrcweir 		// DXSurface::selectTexture
818*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
819*cdf0e10cSrcweir 
820*cdf0e10cSrcweir 		bool DXSurface::selectTexture()
821*cdf0e10cSrcweir 		{
822*cdf0e10cSrcweir 			ImplRenderModuleGuard aGuard( mrRenderModule );
823*cdf0e10cSrcweir 
824*cdf0e10cSrcweir 			mrRenderModule.flushVertexCache();
825*cdf0e10cSrcweir 
826*cdf0e10cSrcweir             D3DTEXTUREHANDLE aTextureHandle;
827*cdf0e10cSrcweir             if(FAILED(mpTexture->GetHandle(
828*cdf0e10cSrcweir                           mrRenderModule.getDevice().get(),
829*cdf0e10cSrcweir                           &aTextureHandle)))
830*cdf0e10cSrcweir             {
831*cdf0e10cSrcweir 				return false;
832*cdf0e10cSrcweir             }
833*cdf0e10cSrcweir 
834*cdf0e10cSrcweir 			// select texture for next primitive
835*cdf0e10cSrcweir             if(FAILED(mrRenderModule.getDevice()->SetRenderState(
836*cdf0e10cSrcweir                           D3DRENDERSTATE_TEXTUREHANDLE,aTextureHandle)))
837*cdf0e10cSrcweir             {
838*cdf0e10cSrcweir 				return false;
839*cdf0e10cSrcweir             }
840*cdf0e10cSrcweir 
841*cdf0e10cSrcweir #if defined(DX_DEBUG_IMAGES)
842*cdf0e10cSrcweir # if OSL_DEBUG_LEVEL > 0
843*cdf0e10cSrcweir 			if( mpSurface.is() )
844*cdf0e10cSrcweir             {
845*cdf0e10cSrcweir                 DDSURFACEDESC aSurfaceDesc;
846*cdf0e10cSrcweir                 rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 );
847*cdf0e10cSrcweir                 aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
848*cdf0e10cSrcweir 
849*cdf0e10cSrcweir                 if( SUCCEEDED(mpSurface->Lock( NULL,
850*cdf0e10cSrcweir                                                &aSurfaceDesc,
851*cdf0e10cSrcweir                                                DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY,
852*cdf0e10cSrcweir                                                NULL)) )
853*cdf0e10cSrcweir                 {
854*cdf0e10cSrcweir                     imdebug( "rgba w=%d h=%d %p",
855*cdf0e10cSrcweir                              aSurfaceDesc.dwWidth,
856*cdf0e10cSrcweir                              aSurfaceDesc.dwHeight,
857*cdf0e10cSrcweir                              aSurfaceDesc.lpSurface );
858*cdf0e10cSrcweir 
859*cdf0e10cSrcweir                     mpSurface->Unlock(NULL);
860*cdf0e10cSrcweir                 }
861*cdf0e10cSrcweir             }
862*cdf0e10cSrcweir # endif
863*cdf0e10cSrcweir #endif
864*cdf0e10cSrcweir 
865*cdf0e10cSrcweir 			return true;
866*cdf0e10cSrcweir 		}
867*cdf0e10cSrcweir 
868*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
869*cdf0e10cSrcweir 		// DXSurface::isValid
870*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
871*cdf0e10cSrcweir 
872*cdf0e10cSrcweir 		bool DXSurface::isValid()
873*cdf0e10cSrcweir 		{
874*cdf0e10cSrcweir 			ImplRenderModuleGuard aGuard( mrRenderModule );
875*cdf0e10cSrcweir 
876*cdf0e10cSrcweir 			if(!(mpSurface.is()))
877*cdf0e10cSrcweir 				return false;
878*cdf0e10cSrcweir 
879*cdf0e10cSrcweir 			if(mpSurface->IsLost() == DDERR_SURFACELOST)
880*cdf0e10cSrcweir             {
881*cdf0e10cSrcweir 				mpSurface->Restore();
882*cdf0e10cSrcweir 				return false;
883*cdf0e10cSrcweir 			}
884*cdf0e10cSrcweir 
885*cdf0e10cSrcweir 			return true;
886*cdf0e10cSrcweir 		}
887*cdf0e10cSrcweir 
888*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
889*cdf0e10cSrcweir 		// DXSurface::update
890*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
891*cdf0e10cSrcweir 
892*cdf0e10cSrcweir 		bool DXSurface::update( const ::basegfx::B2IPoint& rDestPos,
893*cdf0e10cSrcweir 								const ::basegfx::B2IRange& rSourceRect,
894*cdf0e10cSrcweir 								::canvas::IColorBuffer&    rSource )
895*cdf0e10cSrcweir 		{
896*cdf0e10cSrcweir 			ImplRenderModuleGuard aGuard( mrRenderModule );
897*cdf0e10cSrcweir 
898*cdf0e10cSrcweir 			// can't update if surface is not valid, that means
899*cdf0e10cSrcweir 			// either not existent nor restored...
900*cdf0e10cSrcweir 			if(!(isValid()))
901*cdf0e10cSrcweir 				return false;
902*cdf0e10cSrcweir 
903*cdf0e10cSrcweir 			DDSURFACEDESC aSurfaceDesc;
904*cdf0e10cSrcweir 			rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 );
905*cdf0e10cSrcweir 			aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
906*cdf0e10cSrcweir 
907*cdf0e10cSrcweir 			// TODO(P2): only lock the region we want to update
908*cdf0e10cSrcweir 			if( FAILED(mpSurface->Lock( NULL,
909*cdf0e10cSrcweir                                         &aSurfaceDesc,
910*cdf0e10cSrcweir                                         DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_WRITEONLY,
911*cdf0e10cSrcweir                                         NULL)) )
912*cdf0e10cSrcweir 				return false;
913*cdf0e10cSrcweir 
914*cdf0e10cSrcweir 			if(sal_uInt8* pImage = rSource.lock())
915*cdf0e10cSrcweir 			{
916*cdf0e10cSrcweir 				switch( rSource.getFormat() )
917*cdf0e10cSrcweir 				{
918*cdf0e10cSrcweir 					case ::canvas::IColorBuffer::FMT_A8R8G8B8:
919*cdf0e10cSrcweir                     {
920*cdf0e10cSrcweir                         const std::size_t nSourceBytesPerPixel(4);
921*cdf0e10cSrcweir                         const std::size_t nSourcePitchInBytes(rSource.getStride());
922*cdf0e10cSrcweir                         pImage += rSourceRect.getMinY()*nSourcePitchInBytes;
923*cdf0e10cSrcweir                         pImage += rSourceRect.getMinX()*nSourceBytesPerPixel;
924*cdf0e10cSrcweir 
925*cdf0e10cSrcweir                         // calculate the destination memory address
926*cdf0e10cSrcweir                         sal_uInt8 *pDst = ((sal_uInt8*)aSurfaceDesc.lpSurface+
927*cdf0e10cSrcweir                                            (rDestPos.getY()*aSurfaceDesc.lPitch) +
928*cdf0e10cSrcweir                                            (4*rDestPos.getX()));
929*cdf0e10cSrcweir 
930*cdf0e10cSrcweir                         const sal_uInt32 nNumBytesToCopy(
931*cdf0e10cSrcweir                             static_cast<sal_uInt32>(
932*cdf0e10cSrcweir                                 rSourceRect.getWidth())*
933*cdf0e10cSrcweir                             nSourceBytesPerPixel);
934*cdf0e10cSrcweir                         const sal_uInt64 nNumLines(rSourceRect.getHeight());
935*cdf0e10cSrcweir 
936*cdf0e10cSrcweir                         for(sal_uInt32 i=0; i<nNumLines; ++i)
937*cdf0e10cSrcweir                         {
938*cdf0e10cSrcweir                             rtl_copyMemory(pDst,pImage,nNumBytesToCopy);
939*cdf0e10cSrcweir 
940*cdf0e10cSrcweir                             pDst += aSurfaceDesc.lPitch;
941*cdf0e10cSrcweir                             pImage += nSourcePitchInBytes;
942*cdf0e10cSrcweir                         }
943*cdf0e10cSrcweir                     }
944*cdf0e10cSrcweir                     break;
945*cdf0e10cSrcweir 
946*cdf0e10cSrcweir 					case ::canvas::IColorBuffer::FMT_R8G8B8:
947*cdf0e10cSrcweir                     {
948*cdf0e10cSrcweir                         const std::size_t nSourceBytesPerPixel(3);
949*cdf0e10cSrcweir                         const std::size_t nSourcePitchInBytes(rSource.getStride());
950*cdf0e10cSrcweir                         pImage += rSourceRect.getMinY()*nSourcePitchInBytes;
951*cdf0e10cSrcweir                         pImage += rSourceRect.getMinX()*nSourceBytesPerPixel;
952*cdf0e10cSrcweir 
953*cdf0e10cSrcweir                         // calculate the destination memory address
954*cdf0e10cSrcweir                         sal_uInt8 *pDst = ((sal_uInt8*)aSurfaceDesc.lpSurface+
955*cdf0e10cSrcweir                                            (rDestPos.getY()*aSurfaceDesc.lPitch) +
956*cdf0e10cSrcweir                                            (4*rDestPos.getX()));
957*cdf0e10cSrcweir 
958*cdf0e10cSrcweir                         const sal_uInt64 nNumColumns(rSourceRect.getWidth());
959*cdf0e10cSrcweir                         const sal_uInt64 nNumLines(rSourceRect.getHeight());
960*cdf0e10cSrcweir                         for(sal_uInt32 i=0; i<nNumLines; ++i)
961*cdf0e10cSrcweir                         {
962*cdf0e10cSrcweir                             sal_uInt32 *pDstScanline = reinterpret_cast<sal_uInt32 *>(pDst);
963*cdf0e10cSrcweir                             sal_uInt8 *pSrcScanline = reinterpret_cast<sal_uInt8 *>(pImage);
964*cdf0e10cSrcweir                             for(sal_uInt32 x=0; x<nNumColumns; ++x)
965*cdf0e10cSrcweir                             {
966*cdf0e10cSrcweir                                 sal_uInt32 color(0xFF000000);
967*cdf0e10cSrcweir                                 color |= pSrcScanline[2]<<16;
968*cdf0e10cSrcweir                                 color |= pSrcScanline[1]<<8;
969*cdf0e10cSrcweir                                 color |= pSrcScanline[0];
970*cdf0e10cSrcweir                                 pSrcScanline += 3;
971*cdf0e10cSrcweir                                 *pDstScanline++ = color;
972*cdf0e10cSrcweir                             }
973*cdf0e10cSrcweir 
974*cdf0e10cSrcweir                             pDst += aSurfaceDesc.lPitch;
975*cdf0e10cSrcweir                             pImage += nSourcePitchInBytes;
976*cdf0e10cSrcweir                         }
977*cdf0e10cSrcweir                     }
978*cdf0e10cSrcweir                     break;
979*cdf0e10cSrcweir 
980*cdf0e10cSrcweir 					case ::canvas::IColorBuffer::FMT_X8R8G8B8:
981*cdf0e10cSrcweir                     {
982*cdf0e10cSrcweir                         const std::size_t nSourceBytesPerPixel(4);
983*cdf0e10cSrcweir                         const std::size_t nSourcePitchInBytes(rSource.getStride());
984*cdf0e10cSrcweir                         pImage += rSourceRect.getMinY()*nSourcePitchInBytes;
985*cdf0e10cSrcweir                         pImage += rSourceRect.getMinX()*nSourceBytesPerPixel;
986*cdf0e10cSrcweir 
987*cdf0e10cSrcweir                         // calculate the destination memory address
988*cdf0e10cSrcweir                         sal_uInt8 *pDst = ((sal_uInt8*)aSurfaceDesc.lpSurface+
989*cdf0e10cSrcweir                                            (rDestPos.getY()*aSurfaceDesc.lPitch) +
990*cdf0e10cSrcweir                                            (4*rDestPos.getX()));
991*cdf0e10cSrcweir 
992*cdf0e10cSrcweir                         const sal_uInt64 nNumLines(rSourceRect.getHeight());
993*cdf0e10cSrcweir 
994*cdf0e10cSrcweir                         for(sal_uInt32 i=0; i<nNumLines; ++i)
995*cdf0e10cSrcweir                         {
996*cdf0e10cSrcweir                             sal_uInt32 *pSrc32 = reinterpret_cast<sal_uInt32 *>(pImage);
997*cdf0e10cSrcweir                             sal_uInt32 *pDst32 = reinterpret_cast<sal_uInt32 *>(pDst);
998*cdf0e10cSrcweir                             for(sal_uInt32 j=0; j<rSourceRect.getWidth(); ++j)
999*cdf0e10cSrcweir                                 pDst32[j] = 0xFF000000 | pSrc32[j];
1000*cdf0e10cSrcweir 
1001*cdf0e10cSrcweir                             pDst += aSurfaceDesc.lPitch;
1002*cdf0e10cSrcweir                             pImage += nSourcePitchInBytes;
1003*cdf0e10cSrcweir                         }
1004*cdf0e10cSrcweir                     }
1005*cdf0e10cSrcweir                     break;
1006*cdf0e10cSrcweir 
1007*cdf0e10cSrcweir 					default:
1008*cdf0e10cSrcweir 						ENSURE_OR_RETURN_FALSE(false,
1009*cdf0e10cSrcweir                                           "DXSurface::update(): Unknown/unimplemented buffer format" );
1010*cdf0e10cSrcweir 						break;
1011*cdf0e10cSrcweir 				}
1012*cdf0e10cSrcweir 
1013*cdf0e10cSrcweir 				rSource.unlock();
1014*cdf0e10cSrcweir 			}
1015*cdf0e10cSrcweir 
1016*cdf0e10cSrcweir 			return SUCCEEDED(mpSurface->Unlock(NULL));
1017*cdf0e10cSrcweir 		}
1018*cdf0e10cSrcweir 
1019*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1020*cdf0e10cSrcweir 		// DXSurface::getSize
1021*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1022*cdf0e10cSrcweir 
1023*cdf0e10cSrcweir 		::basegfx::B2IVector DXSurface::getSize()
1024*cdf0e10cSrcweir 		{
1025*cdf0e10cSrcweir 			return maSize;
1026*cdf0e10cSrcweir 		}
1027*cdf0e10cSrcweir 
1028*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1029*cdf0e10cSrcweir 		// DXRenderModule::DXRenderModule
1030*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1031*cdf0e10cSrcweir 
1032*cdf0e10cSrcweir 		DXRenderModule::DXRenderModule( const ::Window& rWindow ) :
1033*cdf0e10cSrcweir 	        mhWnd(0),
1034*cdf0e10cSrcweir             mpWindow(),
1035*cdf0e10cSrcweir             maSize(),
1036*cdf0e10cSrcweir 			maSelectedFullscreenMode(),
1037*cdf0e10cSrcweir 	        maTextureFormat(),
1038*cdf0e10cSrcweir             maMonitorInfo(),
1039*cdf0e10cSrcweir 	        mpDirectDraw(),
1040*cdf0e10cSrcweir 			mpPrimarySurface(),
1041*cdf0e10cSrcweir 			mpBackBufferSurface(),
1042*cdf0e10cSrcweir 			mpDirect3D(),
1043*cdf0e10cSrcweir 			mpDirect3DDevice(),
1044*cdf0e10cSrcweir 			maLastUpdate(),
1045*cdf0e10cSrcweir 			maDeviceDesc(),
1046*cdf0e10cSrcweir             maVertexCache(),
1047*cdf0e10cSrcweir 			mnCount(0),
1048*cdf0e10cSrcweir 			mnBeginSceneCount(0),
1049*cdf0e10cSrcweir 			mbPageFlipping( false ),
1050*cdf0e10cSrcweir 			mbHasNoTearingBlt( false ),
1051*cdf0e10cSrcweir 			mbError( false ),
1052*cdf0e10cSrcweir 			meType( PRIMITIVE_TYPE_UNKNOWN ),
1053*cdf0e10cSrcweir 			mpTexture(),
1054*cdf0e10cSrcweir 			maPageSize()
1055*cdf0e10cSrcweir 		{
1056*cdf0e10cSrcweir             // TODO(P2): get rid of those fine-grained locking
1057*cdf0e10cSrcweir 			::osl::MutexGuard aGuard( maMutex );
1058*cdf0e10cSrcweir 
1059*cdf0e10cSrcweir 			if(!(create(rWindow)))
1060*cdf0e10cSrcweir 			{
1061*cdf0e10cSrcweir 				throw lang::NoSupportException(
1062*cdf0e10cSrcweir 					::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
1063*cdf0e10cSrcweir                                          "Could not create DirectX device!") ),NULL);
1064*cdf0e10cSrcweir 			}
1065*cdf0e10cSrcweir 
1066*cdf0e10cSrcweir 			// allocate a single texture surface which can be used later.
1067*cdf0e10cSrcweir 			// we also use this to calibrate the page size.
1068*cdf0e10cSrcweir 			::basegfx::B2IVector aPageSize(
1069*cdf0e10cSrcweir 				::std::min(
1070*cdf0e10cSrcweir 					static_cast<sal_uInt32>(maDeviceDesc.dwMaxTextureWidth),
1071*cdf0e10cSrcweir 					static_cast<sal_uInt32>(MAX_TEXTURE_SIZE)),
1072*cdf0e10cSrcweir 				::std::min(
1073*cdf0e10cSrcweir 					static_cast<sal_uInt32>(maDeviceDesc.dwMaxTextureHeight),
1074*cdf0e10cSrcweir 					static_cast<sal_uInt32>(MAX_TEXTURE_SIZE)));
1075*cdf0e10cSrcweir 			while(true)
1076*cdf0e10cSrcweir 			{
1077*cdf0e10cSrcweir 				mpTexture = ::canvas::ISurfaceSharedPtr(
1078*cdf0e10cSrcweir 					new DXSurface(*this,aPageSize));
1079*cdf0e10cSrcweir 				if(mpTexture->isValid())
1080*cdf0e10cSrcweir 					break;
1081*cdf0e10cSrcweir 
1082*cdf0e10cSrcweir 				aPageSize.setX(aPageSize.getX()>>1);
1083*cdf0e10cSrcweir 				aPageSize.setY(aPageSize.getY()>>1);
1084*cdf0e10cSrcweir 				if((aPageSize.getX() < MIN_TEXTURE_SIZE) ||
1085*cdf0e10cSrcweir 				   (aPageSize.getY() < MIN_TEXTURE_SIZE))
1086*cdf0e10cSrcweir 				{
1087*cdf0e10cSrcweir 					throw lang::NoSupportException(
1088*cdf0e10cSrcweir 						::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
1089*cdf0e10cSrcweir 											"Could not create DirectX device!") ),NULL);
1090*cdf0e10cSrcweir 				}
1091*cdf0e10cSrcweir 			}
1092*cdf0e10cSrcweir 			maPageSize=aPageSize;
1093*cdf0e10cSrcweir 		}
1094*cdf0e10cSrcweir 
1095*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1096*cdf0e10cSrcweir 		// DXRenderModule::create
1097*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1098*cdf0e10cSrcweir 
1099*cdf0e10cSrcweir 		bool DXRenderModule::create( const ::Window& rWindow )
1100*cdf0e10cSrcweir 		{
1101*cdf0e10cSrcweir             // TODO(P2): get rid of those fine-grained locking
1102*cdf0e10cSrcweir 			::osl::MutexGuard aGuard( maMutex );
1103*cdf0e10cSrcweir 
1104*cdf0e10cSrcweir 			maVertexCache.reserve(1024);
1105*cdf0e10cSrcweir 
1106*cdf0e10cSrcweir 			mpWindow.reset(
1107*cdf0e10cSrcweir 				new SystemChildWindow(
1108*cdf0e10cSrcweir 				const_cast<Window *>(&rWindow), 0) );
1109*cdf0e10cSrcweir 
1110*cdf0e10cSrcweir 			// system child window must not receive mouse events
1111*cdf0e10cSrcweir 			mpWindow->SetMouseTransparent( sal_True );
1112*cdf0e10cSrcweir 
1113*cdf0e10cSrcweir 			// parent should receive paint messages as well
1114*cdf0e10cSrcweir 			// [PARENTCLIPMODE_NOCLIP], the argument is here
1115*cdf0e10cSrcweir 			// passed as plain numeric value since the stupid
1116*cdf0e10cSrcweir 			// define utilizes a USHORT cast.
1117*cdf0e10cSrcweir 			mpWindow->SetParentClipMode(0x0002);
1118*cdf0e10cSrcweir 
1119*cdf0e10cSrcweir 			// the system child window must not clear its background
1120*cdf0e10cSrcweir 			mpWindow->EnableEraseBackground( sal_False );
1121*cdf0e10cSrcweir 
1122*cdf0e10cSrcweir 			mpWindow->SetControlForeground();
1123*cdf0e10cSrcweir 			mpWindow->SetControlBackground();
1124*cdf0e10cSrcweir 			mpWindow->EnablePaint(sal_False);
1125*cdf0e10cSrcweir 
1126*cdf0e10cSrcweir 			const SystemEnvData *pData = mpWindow->GetSystemData();
1127*cdf0e10cSrcweir 			const HWND hwnd(reinterpret_cast<HWND>(pData->hWnd));
1128*cdf0e10cSrcweir 			mhWnd = const_cast<HWND>(hwnd);
1129*cdf0e10cSrcweir 
1130*cdf0e10cSrcweir 			ENSURE_OR_THROW( IsWindow( reinterpret_cast<HWND>(mhWnd) ),
1131*cdf0e10cSrcweir                               "DXRenderModuleDXRenderModuleWin32() No valid HWND given." );
1132*cdf0e10cSrcweir 
1133*cdf0e10cSrcweir 			// retrieve position and size of the parent window
1134*cdf0e10cSrcweir 			const ::Size &rSizePixel(rWindow.GetSizePixel());
1135*cdf0e10cSrcweir 
1136*cdf0e10cSrcweir 			// remember the size of the parent window, since we
1137*cdf0e10cSrcweir 			// need to use this for our child window.
1138*cdf0e10cSrcweir 			maSize.setX(static_cast<sal_Int32>(rSizePixel.Width()));
1139*cdf0e10cSrcweir 			maSize.setY(static_cast<sal_Int32>(rSizePixel.Height()));
1140*cdf0e10cSrcweir 
1141*cdf0e10cSrcweir 			// let the child window cover the same size as the parent window.
1142*cdf0e10cSrcweir 			mpWindow->SetPosSizePixel(0,0,maSize.getX(),maSize.getY());
1143*cdf0e10cSrcweir 
1144*cdf0e10cSrcweir             MonitorList aMonitorList;
1145*cdf0e10cSrcweir             fillMonitorList( aMonitorList );
1146*cdf0e10cSrcweir 
1147*cdf0e10cSrcweir  			mpDirectDraw = COMReference<IDirectDraw2>(
1148*cdf0e10cSrcweir                 createDirectDraw(aMonitorList, maMonitorInfo, mhWnd));
1149*cdf0e10cSrcweir 
1150*cdf0e10cSrcweir 			if(!mpDirectDraw.is())
1151*cdf0e10cSrcweir 				return false;
1152*cdf0e10cSrcweir 
1153*cdf0e10cSrcweir 			if( !queryCaps() )
1154*cdf0e10cSrcweir 			{
1155*cdf0e10cSrcweir 				// go defunct, and exit
1156*cdf0e10cSrcweir 				VERBOSE_TRACE( "Device::Device(): GetCaps failed" );
1157*cdf0e10cSrcweir 				mpDirectDraw.reset();
1158*cdf0e10cSrcweir 				return false;
1159*cdf0e10cSrcweir 			}
1160*cdf0e10cSrcweir 
1161*cdf0e10cSrcweir 			if( !validateCaps() )
1162*cdf0e10cSrcweir 			{
1163*cdf0e10cSrcweir 				// go defunct, and exit
1164*cdf0e10cSrcweir 				VERBOSE_TRACE( "Device::Device(): Insufficient DirectX capabilities, failed" );
1165*cdf0e10cSrcweir 				mpDirectDraw.reset();
1166*cdf0e10cSrcweir 				return false;
1167*cdf0e10cSrcweir 			}
1168*cdf0e10cSrcweir 
1169*cdf0e10cSrcweir 			if( FAILED( mpDirectDraw->SetCooperativeLevel( mhWnd,
1170*cdf0e10cSrcweir                                                            DDSCL_NORMAL|DDSCL_MULTITHREADED|DDSCL_FPUPRESERVE ) ) )
1171*cdf0e10cSrcweir 			{
1172*cdf0e10cSrcweir 				// go defunct, and exit
1173*cdf0e10cSrcweir 				VERBOSE_TRACE( "Device::Device(): SetCooperativeLevel failed" );
1174*cdf0e10cSrcweir 				mpDirectDraw.reset();
1175*cdf0e10cSrcweir 				return false;
1176*cdf0e10cSrcweir 			}
1177*cdf0e10cSrcweir 
1178*cdf0e10cSrcweir 			// setup query struct
1179*cdf0e10cSrcweir 			rtl_fillMemory( &maSelectedFullscreenMode.selectedDesc,
1180*cdf0e10cSrcweir 							sizeof(DDSURFACEDESC), 0 );
1181*cdf0e10cSrcweir 			maSelectedFullscreenMode.selectedDesc.dwSize = sizeof(DDSURFACEDESC);
1182*cdf0e10cSrcweir 
1183*cdf0e10cSrcweir 			// read current display mode, e.g. for screen dimension
1184*cdf0e10cSrcweir 			if( FAILED( mpDirectDraw->GetDisplayMode( &maSelectedFullscreenMode.selectedDesc )) )
1185*cdf0e10cSrcweir 			{
1186*cdf0e10cSrcweir 				// go defunct, and exit
1187*cdf0e10cSrcweir 				VERBOSE_TRACE( "Device::Device(): GetDisplayMode failed" );
1188*cdf0e10cSrcweir 				mpDirectDraw.reset();
1189*cdf0e10cSrcweir 				return false;
1190*cdf0e10cSrcweir 			}
1191*cdf0e10cSrcweir 
1192*cdf0e10cSrcweir 			// check for supported primary surface formats...
1193*cdf0e10cSrcweir 			unsigned int nDisplayFormat = getDisplayFormat() & 0x00000FFF;
1194*cdf0e10cSrcweir 			if(nDisplayFormat != 0x888 && nDisplayFormat != 0x565)
1195*cdf0e10cSrcweir             {
1196*cdf0e10cSrcweir 				// go defunct, and exit
1197*cdf0e10cSrcweir 				VERBOSE_TRACE( "Device::Device(): Unsupported DisplayFormat" );
1198*cdf0e10cSrcweir 				mpDirectDraw.reset();
1199*cdf0e10cSrcweir 				return false;
1200*cdf0e10cSrcweir 			}
1201*cdf0e10cSrcweir 
1202*cdf0e10cSrcweir 			// create primary surface reference
1203*cdf0e10cSrcweir 			DDSURFACEDESC 		aSurfaceDesc;
1204*cdf0e10cSrcweir 			IDirectDrawSurface* pPrimarySurface;
1205*cdf0e10cSrcweir 
1206*cdf0e10cSrcweir 			rtl_fillMemory( &aSurfaceDesc,
1207*cdf0e10cSrcweir 							sizeof(DDSURFACEDESC), 0 );
1208*cdf0e10cSrcweir 			aSurfaceDesc.dwSize = sizeof(aSurfaceDesc);
1209*cdf0e10cSrcweir 			aSurfaceDesc.dwFlags = DDSD_CAPS;
1210*cdf0e10cSrcweir 			aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
1211*cdf0e10cSrcweir 
1212*cdf0e10cSrcweir 			if( FAILED(mpDirectDraw->CreateSurface(&aSurfaceDesc, &pPrimarySurface, NULL)) )
1213*cdf0e10cSrcweir 			{
1214*cdf0e10cSrcweir 				// go defunct, and exit
1215*cdf0e10cSrcweir 				VERBOSE_TRACE( "Device::Device(): CreateSurface failed" );
1216*cdf0e10cSrcweir 				mpDirectDraw.reset();
1217*cdf0e10cSrcweir 				return false;
1218*cdf0e10cSrcweir 			}
1219*cdf0e10cSrcweir 
1220*cdf0e10cSrcweir 			mpPrimarySurface = COMReference< IDirectDrawSurface >(pPrimarySurface);
1221*cdf0e10cSrcweir 
1222*cdf0e10cSrcweir 			// create a Clipper and associate it with the primary surface
1223*cdf0e10cSrcweir 			// and the render window
1224*cdf0e10cSrcweir 			LPDIRECTDRAWCLIPPER pClipper;
1225*cdf0e10cSrcweir 			if( FAILED(mpDirectDraw->CreateClipper( 0, &pClipper, NULL )) )
1226*cdf0e10cSrcweir 			{
1227*cdf0e10cSrcweir 				// go defunct, and exit
1228*cdf0e10cSrcweir 				VERBOSE_TRACE( "Device::Device(): CreateClipper failed" );
1229*cdf0e10cSrcweir 				mpPrimarySurface.reset();
1230*cdf0e10cSrcweir 				mpDirectDraw.reset();
1231*cdf0e10cSrcweir 				return false;
1232*cdf0e10cSrcweir 			}
1233*cdf0e10cSrcweir 			if( FAILED(pClipper->SetHWnd(0, mhWnd)) )
1234*cdf0e10cSrcweir 			{
1235*cdf0e10cSrcweir 				// go defunct, and exit
1236*cdf0e10cSrcweir 				VERBOSE_TRACE( "Device::Device(): Clipper->SetHWnd failed" );
1237*cdf0e10cSrcweir 				pClipper->Release();
1238*cdf0e10cSrcweir 				mpPrimarySurface.reset();
1239*cdf0e10cSrcweir 				mpDirectDraw.reset();
1240*cdf0e10cSrcweir 				return false;
1241*cdf0e10cSrcweir 			}
1242*cdf0e10cSrcweir 			if( FAILED(mpPrimarySurface->SetClipper( pClipper )) )
1243*cdf0e10cSrcweir 			{
1244*cdf0e10cSrcweir 				// go defunct, and exit
1245*cdf0e10cSrcweir 				VERBOSE_TRACE( "Device::Device(): SetClipper failed" );
1246*cdf0e10cSrcweir 				pClipper->Release();
1247*cdf0e10cSrcweir 				mpPrimarySurface.reset();
1248*cdf0e10cSrcweir 				mpDirectDraw.reset();
1249*cdf0e10cSrcweir 				return false;
1250*cdf0e10cSrcweir 			}
1251*cdf0e10cSrcweir 
1252*cdf0e10cSrcweir 			// clipper is now owned by mpPrimarySurface, release our reference
1253*cdf0e10cSrcweir 			pClipper->Release();
1254*cdf0e10cSrcweir 
1255*cdf0e10cSrcweir 			// TODO(F3): Check whether palette needs any setup here
1256*cdf0e10cSrcweir 
1257*cdf0e10cSrcweir 			// get us a backbuffer for simulated flipping
1258*cdf0e10cSrcweir 			IDirectDrawSurface* pSurface;
1259*cdf0e10cSrcweir 
1260*cdf0e10cSrcweir 			// Strictly speaking, we don't need a full screen worth of
1261*cdf0e10cSrcweir 			// backbuffer here. We could also scale dynamically with
1262*cdf0e10cSrcweir 			// the current window size, but this will make it
1263*cdf0e10cSrcweir 			// necessary to temporarily have two buffers while copying
1264*cdf0e10cSrcweir 			// from the old to the new one. What's more, at the time
1265*cdf0e10cSrcweir 			// we need a larger buffer, DX might not have sufficient
1266*cdf0e10cSrcweir 			// resources available, and we're then left with too small
1267*cdf0e10cSrcweir 			// a back buffer, and no way of falling back to a
1268*cdf0e10cSrcweir 			// different canvas implementation.
1269*cdf0e10cSrcweir 			const ::basegfx::B2ISize aSize( getFramebufferSize() );
1270*cdf0e10cSrcweir 
1271*cdf0e10cSrcweir 			rtl_fillMemory( &aSurfaceDesc,
1272*cdf0e10cSrcweir 							sizeof(DDSURFACEDESC), 0 );
1273*cdf0e10cSrcweir 			aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
1274*cdf0e10cSrcweir 			aSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1275*cdf0e10cSrcweir 			aSurfaceDesc.dwHeight= aSize.getY();
1276*cdf0e10cSrcweir 			aSurfaceDesc.dwWidth = aSize.getX();
1277*cdf0e10cSrcweir 
1278*cdf0e10cSrcweir 			aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
1279*cdf0e10cSrcweir 
1280*cdf0e10cSrcweir 			HRESULT nRes = mpDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
1281*cdf0e10cSrcweir 
1282*cdf0e10cSrcweir 			if( FAILED( nRes ) )
1283*cdf0e10cSrcweir 			{
1284*cdf0e10cSrcweir 				if( nRes == DDERR_OUTOFVIDEOMEMORY )
1285*cdf0e10cSrcweir 				{
1286*cdf0e10cSrcweir 					// local vid mem failed. Maybe AGP mem works?
1287*cdf0e10cSrcweir 					aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM;
1288*cdf0e10cSrcweir 					if( FAILED(mpDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL)) )
1289*cdf0e10cSrcweir 					{
1290*cdf0e10cSrcweir 						// no chance, go defunct, and exit
1291*cdf0e10cSrcweir 						VERBOSE_TRACE( "Device::Device(): CreateSurface for backbuffer failed" );
1292*cdf0e10cSrcweir 						mpPrimarySurface.reset();
1293*cdf0e10cSrcweir 						mpDirectDraw.reset();
1294*cdf0e10cSrcweir 						return false;
1295*cdf0e10cSrcweir 					}
1296*cdf0e10cSrcweir 
1297*cdf0e10cSrcweir 					VERBOSE_TRACE( "Device::Device(): CreateSurface for backbuffer reverted to non-local video mem" );
1298*cdf0e10cSrcweir 				}
1299*cdf0e10cSrcweir 				else
1300*cdf0e10cSrcweir 				{
1301*cdf0e10cSrcweir 					// no chance, go defunct, and exit
1302*cdf0e10cSrcweir 					VERBOSE_TRACE( "Device::Device(): CreateSurface for backbuffer failed" );
1303*cdf0e10cSrcweir 					mpPrimarySurface.reset();
1304*cdf0e10cSrcweir 					mpDirectDraw.reset();
1305*cdf0e10cSrcweir 					return false;
1306*cdf0e10cSrcweir 				}
1307*cdf0e10cSrcweir 			}
1308*cdf0e10cSrcweir 
1309*cdf0e10cSrcweir 			VERBOSE_TRACE( "Device::Device(): created backbuffer of size %d times %d pixel",
1310*cdf0e10cSrcweir                            aSurfaceDesc.dwWidth,
1311*cdf0e10cSrcweir                            aSurfaceDesc.dwHeight );
1312*cdf0e10cSrcweir 
1313*cdf0e10cSrcweir 			mpBackBufferSurface = COMReference< IDirectDrawSurface >(pSurface);
1314*cdf0e10cSrcweir 			clearSurface(mpBackBufferSurface);
1315*cdf0e10cSrcweir 
1316*cdf0e10cSrcweir 			if( !setup3DDevice() )
1317*cdf0e10cSrcweir 			{
1318*cdf0e10cSrcweir 				// go defunct, and exit
1319*cdf0e10cSrcweir 				VERBOSE_TRACE( "Device::Device(): setup3DDevice failed" );
1320*cdf0e10cSrcweir 				mpBackBufferSurface.reset();
1321*cdf0e10cSrcweir 				mpPrimarySurface.reset();
1322*cdf0e10cSrcweir 				mpDirectDraw.reset();
1323*cdf0e10cSrcweir 				return false;
1324*cdf0e10cSrcweir 			}
1325*cdf0e10cSrcweir 
1326*cdf0e10cSrcweir 			mpWindow->Show();
1327*cdf0e10cSrcweir 
1328*cdf0e10cSrcweir 			return true;
1329*cdf0e10cSrcweir 		}
1330*cdf0e10cSrcweir 
1331*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1332*cdf0e10cSrcweir 		// DXRenderModule::getSize
1333*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1334*cdf0e10cSrcweir 
1335*cdf0e10cSrcweir 		::basegfx::B2ISize DXRenderModule::getFramebufferSize() const
1336*cdf0e10cSrcweir 		{
1337*cdf0e10cSrcweir             return mpDirectDraw.is() ?
1338*cdf0e10cSrcweir                 ::basegfx::B2ISize( maSelectedFullscreenMode.selectedDesc.dwWidth,
1339*cdf0e10cSrcweir                                     maSelectedFullscreenMode.selectedDesc.dwHeight ) :
1340*cdf0e10cSrcweir                 ::basegfx::B2ISize();
1341*cdf0e10cSrcweir 		}
1342*cdf0e10cSrcweir 
1343*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1344*cdf0e10cSrcweir 		// DXRenderModule::setup3DDevice
1345*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1346*cdf0e10cSrcweir 
1347*cdf0e10cSrcweir 		bool DXRenderModule::setup3DDevice()
1348*cdf0e10cSrcweir 		{
1349*cdf0e10cSrcweir 			// create and setup 3D device
1350*cdf0e10cSrcweir 			// ==========================
1351*cdf0e10cSrcweir 			LPDIRECT3D2	pDirect3D;
1352*cdf0e10cSrcweir 			if( FAILED( mpDirectDraw->QueryInterface( IID_IDirect3D2, (LPVOID*)&pDirect3D ) ) )
1353*cdf0e10cSrcweir 			{
1354*cdf0e10cSrcweir 				// go defunct, and exit
1355*cdf0e10cSrcweir 				VERBOSE_TRACE( "Device::setup3DDevice(): QueryInterface() for Direct3D failed" );
1356*cdf0e10cSrcweir 				return false;
1357*cdf0e10cSrcweir 			}
1358*cdf0e10cSrcweir 
1359*cdf0e10cSrcweir 			mpDirect3D = COMReference< IDirect3D2 >(pDirect3D);
1360*cdf0e10cSrcweir 
1361*cdf0e10cSrcweir 			LPDIRECT3DDEVICE2 pDirect3DDevice;
1362*cdf0e10cSrcweir 			// try HW-accelerated device first
1363*cdf0e10cSrcweir 			if( FAILED(mpDirect3D->CreateDevice( IID_IDirect3DHALDevice,
1364*cdf0e10cSrcweir                                                  mpBackBufferSurface.get(),
1365*cdf0e10cSrcweir                                                  &pDirect3DDevice )) )
1366*cdf0e10cSrcweir 			{
1367*cdf0e10cSrcweir 				// no HW 3D support - go defunct, and exit
1368*cdf0e10cSrcweir 				VERBOSE_TRACE( "Device::setup3DDevice(): CreateDevice() for HW Direct3D rendering failed" );
1369*cdf0e10cSrcweir 				mpDirect3D.reset();
1370*cdf0e10cSrcweir 				return false;
1371*cdf0e10cSrcweir 			}
1372*cdf0e10cSrcweir 
1373*cdf0e10cSrcweir 			D3DDEVICEDESC aHELDeviceDesc;
1374*cdf0e10cSrcweir 			rtl_fillMemory(&maDeviceDesc,sizeof(maDeviceDesc),0);
1375*cdf0e10cSrcweir 			rtl_fillMemory(&aHELDeviceDesc,sizeof(aHELDeviceDesc),0);
1376*cdf0e10cSrcweir 			maDeviceDesc.dwSize = sizeof(maDeviceDesc);
1377*cdf0e10cSrcweir 			aHELDeviceDesc.dwSize = sizeof(aHELDeviceDesc);
1378*cdf0e10cSrcweir 			if(FAILED(pDirect3DDevice->GetCaps(&maDeviceDesc,&aHELDeviceDesc)))
1379*cdf0e10cSrcweir             {
1380*cdf0e10cSrcweir 				// go defunct, and exit
1381*cdf0e10cSrcweir 				VERBOSE_TRACE( "Device::setup3DDevice(): GetCaps() for Direct3DDevice failed" );
1382*cdf0e10cSrcweir 				mpDirect3D.reset();
1383*cdf0e10cSrcweir 				return false;
1384*cdf0e10cSrcweir 			}
1385*cdf0e10cSrcweir 
1386*cdf0e10cSrcweir 			mpDirect3DDevice = COMReference< IDirect3DDevice2 >(pDirect3DDevice);
1387*cdf0e10cSrcweir 
1388*cdf0e10cSrcweir 			// select appropriate texture format (_need_ alpha channel here)
1389*cdf0e10cSrcweir 			rtl_fillMemory( &maTextureFormat,
1390*cdf0e10cSrcweir 							sizeof(DDPIXELFORMAT), 0 );
1391*cdf0e10cSrcweir 			maTextureFormat.dwSize = sizeof(DDPIXELFORMAT);
1392*cdf0e10cSrcweir 			if( SUCCEEDED(mpDirect3DDevice->EnumTextureFormats( EnumTextureFormatsCallback, &maTextureFormat )) )
1393*cdf0e10cSrcweir 			{
1394*cdf0e10cSrcweir 				bool bSupportedFormat = true;
1395*cdf0e10cSrcweir 				if((maTextureFormat.dwFlags & (DDPF_ALPHAPIXELS | DDPF_RGB)) != (DDPF_ALPHAPIXELS | DDPF_RGB))
1396*cdf0e10cSrcweir 					bSupportedFormat = false;
1397*cdf0e10cSrcweir 				else if(maTextureFormat.dwRGBAlphaBitMask != 0xFF000000)
1398*cdf0e10cSrcweir 					bSupportedFormat = false;
1399*cdf0e10cSrcweir 				else if(maTextureFormat.dwRBitMask != 0x00FF0000)
1400*cdf0e10cSrcweir 					bSupportedFormat = false;
1401*cdf0e10cSrcweir 				else if(maTextureFormat.dwGBitMask != 0x0000FF00)
1402*cdf0e10cSrcweir 					bSupportedFormat = false;
1403*cdf0e10cSrcweir 				else if(maTextureFormat.dwBBitMask != 0x000000FF)
1404*cdf0e10cSrcweir 					bSupportedFormat = false;
1405*cdf0e10cSrcweir 
1406*cdf0e10cSrcweir 				if(bSupportedFormat)
1407*cdf0e10cSrcweir                 {
1408*cdf0e10cSrcweir 					VERBOSE_TRACE( "Device::setup3DDevice(): chose texture format dwRGBBitCount %d, dwRBitMask %x, "
1409*cdf0e10cSrcweir                                    "dwGBitMask %x, dwBBitMask %x and dwRGBAlphaBitMask %x. The texture uses %s alpha.",
1410*cdf0e10cSrcweir                                    maTextureFormat.dwRGBBitCount,
1411*cdf0e10cSrcweir                                    maTextureFormat.dwRBitMask,
1412*cdf0e10cSrcweir                                    maTextureFormat.dwGBitMask,
1413*cdf0e10cSrcweir                                    maTextureFormat.dwBBitMask,
1414*cdf0e10cSrcweir                                    maTextureFormat.dwRGBAlphaBitMask,
1415*cdf0e10cSrcweir                                    maTextureFormat.dwFlags & DDPF_ALPHAPREMULT ? "premultiplied" : "non-premultiplied" );
1416*cdf0e10cSrcweir 
1417*cdf0e10cSrcweir 					// setup the device (with as much as we can possibly do here)
1418*cdf0e10cSrcweir 					// ==========================================================
1419*cdf0e10cSrcweir 
1420*cdf0e10cSrcweir 					LPDIRECT3DVIEWPORT2	pViewport;
1421*cdf0e10cSrcweir 
1422*cdf0e10cSrcweir 					if( SUCCEEDED(mpDirect3D->CreateViewport( &pViewport, NULL )) )
1423*cdf0e10cSrcweir 					{
1424*cdf0e10cSrcweir 						if( SUCCEEDED(mpDirect3DDevice->AddViewport( pViewport )) )
1425*cdf0e10cSrcweir 						{
1426*cdf0e10cSrcweir 							// setup viewport (to whole backbuffer)
1427*cdf0e10cSrcweir 							D3DVIEWPORT2 aViewport;
1428*cdf0e10cSrcweir 
1429*cdf0e10cSrcweir 							aViewport.dwSize = sizeof(D3DVIEWPORT2);
1430*cdf0e10cSrcweir 							aViewport.dwX = 0;
1431*cdf0e10cSrcweir 							aViewport.dwY = 0;
1432*cdf0e10cSrcweir 							aViewport.dwWidth = maSelectedFullscreenMode.selectedDesc.dwWidth;
1433*cdf0e10cSrcweir 							aViewport.dwHeight = maSelectedFullscreenMode.selectedDesc.dwHeight;
1434*cdf0e10cSrcweir 							aViewport.dvClipX = -1.0;
1435*cdf0e10cSrcweir 							aViewport.dvClipY =  -1.0;
1436*cdf0e10cSrcweir 							aViewport.dvClipWidth  = 2.0;
1437*cdf0e10cSrcweir 							aViewport.dvClipHeight = 2.0;
1438*cdf0e10cSrcweir 							aViewport.dvMinZ = 0.0;
1439*cdf0e10cSrcweir 							aViewport.dvMaxZ = 1.0;
1440*cdf0e10cSrcweir 
1441*cdf0e10cSrcweir 							if( SUCCEEDED(pViewport->SetViewport2( &aViewport )) )
1442*cdf0e10cSrcweir 							{
1443*cdf0e10cSrcweir 								if( SUCCEEDED(mpDirect3DDevice->SetCurrentViewport( pViewport )) )
1444*cdf0e10cSrcweir 								{
1445*cdf0e10cSrcweir 									// Viewport was handed over to 3DDevice, thus we can release now
1446*cdf0e10cSrcweir 									pViewport->Release();
1447*cdf0e10cSrcweir 
1448*cdf0e10cSrcweir 									// currently, no need for any
1449*cdf0e10cSrcweir 									// matrix or light source
1450*cdf0e10cSrcweir 									// setup, since we only render
1451*cdf0e10cSrcweir 									// transformed&lighted
1452*cdf0e10cSrcweir 									// vertices
1453*cdf0e10cSrcweir 
1454*cdf0e10cSrcweir 									// done; successfully
1455*cdf0e10cSrcweir 									return true;
1456*cdf0e10cSrcweir 								}
1457*cdf0e10cSrcweir 								else
1458*cdf0e10cSrcweir 								{
1459*cdf0e10cSrcweir 									VERBOSE_TRACE( "Device::setup3DDevice(): SetCurrentViewport failed" );
1460*cdf0e10cSrcweir 								}
1461*cdf0e10cSrcweir 							}
1462*cdf0e10cSrcweir 							else
1463*cdf0e10cSrcweir 							{
1464*cdf0e10cSrcweir 								VERBOSE_TRACE( "Device::setup3DDevice(): SetViewport2 failed" );
1465*cdf0e10cSrcweir 							}
1466*cdf0e10cSrcweir 						}
1467*cdf0e10cSrcweir 						else
1468*cdf0e10cSrcweir 						{
1469*cdf0e10cSrcweir 							VERBOSE_TRACE( "Device::setup3DDevice(): AddViewport failed" );
1470*cdf0e10cSrcweir 						}
1471*cdf0e10cSrcweir 
1472*cdf0e10cSrcweir 						pViewport->Release();
1473*cdf0e10cSrcweir 					}
1474*cdf0e10cSrcweir 					else
1475*cdf0e10cSrcweir 					{
1476*cdf0e10cSrcweir 						VERBOSE_TRACE( "Device::setup3DDevice(): CreateViewport failed" );
1477*cdf0e10cSrcweir 					}
1478*cdf0e10cSrcweir 				}
1479*cdf0e10cSrcweir 				else
1480*cdf0e10cSrcweir 				{
1481*cdf0e10cSrcweir 					VERBOSE_TRACE( "Device::setup3DDevice(): No supported pixelformat" );
1482*cdf0e10cSrcweir 				}
1483*cdf0e10cSrcweir 			}
1484*cdf0e10cSrcweir 			else
1485*cdf0e10cSrcweir 			{
1486*cdf0e10cSrcweir 				VERBOSE_TRACE( "Device::setup3DDevice(): EnumTextureFormats failed" );
1487*cdf0e10cSrcweir 			}
1488*cdf0e10cSrcweir 
1489*cdf0e10cSrcweir 			// go defunct, and exit
1490*cdf0e10cSrcweir 			mpDirect3DDevice.reset();
1491*cdf0e10cSrcweir 			mpDirect3D.reset();
1492*cdf0e10cSrcweir 
1493*cdf0e10cSrcweir 			return false;
1494*cdf0e10cSrcweir 		}
1495*cdf0e10cSrcweir 
1496*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1497*cdf0e10cSrcweir 		// DXRenderModule::queryCaps
1498*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1499*cdf0e10cSrcweir 
1500*cdf0e10cSrcweir 		bool DXRenderModule::queryCaps()
1501*cdf0e10cSrcweir 		{
1502*cdf0e10cSrcweir 			DDCAPS	aHWCaps;
1503*cdf0e10cSrcweir 			DDCAPS	aHELCaps;
1504*cdf0e10cSrcweir 
1505*cdf0e10cSrcweir 			rtl_fillMemory( &aHWCaps,
1506*cdf0e10cSrcweir 							sizeof(aHWCaps), 0 );
1507*cdf0e10cSrcweir 			rtl_fillMemory( &aHELCaps,
1508*cdf0e10cSrcweir 							sizeof(aHELCaps), 0 );
1509*cdf0e10cSrcweir 			aHWCaps.dwSize = sizeof( aHWCaps );
1510*cdf0e10cSrcweir 			aHELCaps.dwSize = sizeof( aHELCaps );
1511*cdf0e10cSrcweir 
1512*cdf0e10cSrcweir 			if( FAILED( mpDirectDraw->GetCaps( &aHWCaps,
1513*cdf0e10cSrcweir 											&aHELCaps ) ) )
1514*cdf0e10cSrcweir 			{
1515*cdf0e10cSrcweir 				return false;
1516*cdf0e10cSrcweir 			}
1517*cdf0e10cSrcweir 
1518*cdf0e10cSrcweir 			mbHasNoTearingBlt = aHWCaps.dwFXCaps & DDBLTFX_NOTEARING;
1519*cdf0e10cSrcweir 
1520*cdf0e10cSrcweir 			VERBOSE_TRACE( "dxcanvas initialization: %d bytes VRAM free for surfaces (%d with AGP mem), "
1521*cdf0e10cSrcweir                            "%d bytes VRAM free for textures (%d with AGP mem)",
1522*cdf0e10cSrcweir                            getAvailableSurfaceMem( false ),
1523*cdf0e10cSrcweir                            getAvailableSurfaceMem( true ),
1524*cdf0e10cSrcweir                            getAvailableTextureMem( false ),
1525*cdf0e10cSrcweir                            getAvailableTextureMem( true ) );
1526*cdf0e10cSrcweir 
1527*cdf0e10cSrcweir 			return true;
1528*cdf0e10cSrcweir 		}
1529*cdf0e10cSrcweir 
1530*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1531*cdf0e10cSrcweir 		// DXRenderModule::validateCaps
1532*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1533*cdf0e10cSrcweir 
1534*cdf0e10cSrcweir 		bool DXRenderModule::validateCaps()
1535*cdf0e10cSrcweir 		{
1536*cdf0e10cSrcweir 			// TODO(E3): Validate HW capabilities. Depending on primary
1537*cdf0e10cSrcweir 			// surface size, reject HW e.g. on the grounds of insufficient
1538*cdf0e10cSrcweir 			// VRAM.
1539*cdf0e10cSrcweir 
1540*cdf0e10cSrcweir 			// setup query struct
1541*cdf0e10cSrcweir 			DDSURFACEDESC desc;
1542*cdf0e10cSrcweir 			rtl_fillMemory(&desc,sizeof(DDSURFACEDESC),0);
1543*cdf0e10cSrcweir 			desc.dwSize = sizeof(DDSURFACEDESC);
1544*cdf0e10cSrcweir 
1545*cdf0e10cSrcweir 			// read current display mode, e.g. for screen dimension
1546*cdf0e10cSrcweir 			if(FAILED( mpDirectDraw->GetDisplayMode(&desc)))
1547*cdf0e10cSrcweir 				return false;
1548*cdf0e10cSrcweir 
1549*cdf0e10cSrcweir 			// simple heuristic: we need at least 3 times the desktop
1550*cdf0e10cSrcweir 			// resolution based on ARGB color values...
1551*cdf0e10cSrcweir 			std::size_t nMinimumVRAMSize = ((desc.dwWidth*desc.dwHeight)<<2)*3;
1552*cdf0e10cSrcweir 			if(getAvailableSurfaceMem() < nMinimumVRAMSize)
1553*cdf0e10cSrcweir 				return false;
1554*cdf0e10cSrcweir 
1555*cdf0e10cSrcweir 			return true;
1556*cdf0e10cSrcweir 		}
1557*cdf0e10cSrcweir 
1558*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1559*cdf0e10cSrcweir 		// DXRenderModule::getDisplayFormat
1560*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1561*cdf0e10cSrcweir 
1562*cdf0e10cSrcweir 		unsigned int DXRenderModule::getDisplayFormat() const
1563*cdf0e10cSrcweir 		{
1564*cdf0e10cSrcweir 			unsigned int nFormat;
1565*cdf0e10cSrcweir 			nFormat  = ::canvas::tools::bitcount32(maSelectedFullscreenMode.selectedDesc.ddpfPixelFormat.dwRGBAlphaBitMask)<<12;
1566*cdf0e10cSrcweir 			nFormat |= ::canvas::tools::bitcount32(maSelectedFullscreenMode.selectedDesc.ddpfPixelFormat.dwRBitMask)<<8;
1567*cdf0e10cSrcweir 			nFormat |= ::canvas::tools::bitcount32(maSelectedFullscreenMode.selectedDesc.ddpfPixelFormat.dwGBitMask)<<4;
1568*cdf0e10cSrcweir 			nFormat |= ::canvas::tools::bitcount32(maSelectedFullscreenMode.selectedDesc.ddpfPixelFormat.dwBBitMask);
1569*cdf0e10cSrcweir 			return nFormat;
1570*cdf0e10cSrcweir 		}
1571*cdf0e10cSrcweir 
1572*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1573*cdf0e10cSrcweir 		// DXRenderModule::getAvailableSurfaceMem
1574*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1575*cdf0e10cSrcweir 
1576*cdf0e10cSrcweir 		std::size_t DXRenderModule::getAvailableSurfaceMem( bool bWithAGPMem ) const
1577*cdf0e10cSrcweir 		{
1578*cdf0e10cSrcweir 			if( !mpDirectDraw.is() )
1579*cdf0e10cSrcweir 				return 0;
1580*cdf0e10cSrcweir 
1581*cdf0e10cSrcweir 			std::size_t nRes( 0 );
1582*cdf0e10cSrcweir 
1583*cdf0e10cSrcweir 			DDSCAPS aSurfaceCaps;
1584*cdf0e10cSrcweir 			DWORD	nTotal, nFree;
1585*cdf0e10cSrcweir 
1586*cdf0e10cSrcweir 			// real VRAM (const_cast, since GetAvailableVidMem is non-const)
1587*cdf0e10cSrcweir 			aSurfaceCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
1588*cdf0e10cSrcweir 			if( FAILED(const_cast<IDirectDraw2&>(*mpDirectDraw).GetAvailableVidMem( &aSurfaceCaps, &nTotal, &nFree )) )
1589*cdf0e10cSrcweir 				return 0;
1590*cdf0e10cSrcweir 
1591*cdf0e10cSrcweir 			nRes += nFree;
1592*cdf0e10cSrcweir 
1593*cdf0e10cSrcweir 			if( bWithAGPMem )
1594*cdf0e10cSrcweir 			{
1595*cdf0e10cSrcweir 				// AGP RAM (const_cast, since GetAvailableVidMem is non-const)
1596*cdf0e10cSrcweir 				aSurfaceCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM;
1597*cdf0e10cSrcweir 				if( FAILED(const_cast<IDirectDraw2&>(*mpDirectDraw).GetAvailableVidMem( &aSurfaceCaps, &nTotal, &nFree )) )
1598*cdf0e10cSrcweir 					return 0;
1599*cdf0e10cSrcweir 
1600*cdf0e10cSrcweir 				nRes += nFree;
1601*cdf0e10cSrcweir 			}
1602*cdf0e10cSrcweir 
1603*cdf0e10cSrcweir 			return nRes;
1604*cdf0e10cSrcweir 		}
1605*cdf0e10cSrcweir 
1606*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1607*cdf0e10cSrcweir 		// DXRenderModule::getAvailableTextureMem
1608*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1609*cdf0e10cSrcweir 
1610*cdf0e10cSrcweir 		std::size_t DXRenderModule::getAvailableTextureMem( bool bWithAGPMem ) const
1611*cdf0e10cSrcweir 		{
1612*cdf0e10cSrcweir 			if( !mpDirectDraw.is() )
1613*cdf0e10cSrcweir 				return 0;
1614*cdf0e10cSrcweir 
1615*cdf0e10cSrcweir 			std::size_t nRes( 0 );
1616*cdf0e10cSrcweir 
1617*cdf0e10cSrcweir 			DDSCAPS aSurfaceCaps;
1618*cdf0e10cSrcweir 			DWORD	nTotal, nFree;
1619*cdf0e10cSrcweir 
1620*cdf0e10cSrcweir 			// TODO(F1): Check if flags are applicable
1621*cdf0e10cSrcweir 
1622*cdf0e10cSrcweir 			// real VRAM (const_cast, since GetAvailableVidMem is non-const)
1623*cdf0e10cSrcweir 			aSurfaceCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
1624*cdf0e10cSrcweir 			if( FAILED(const_cast<IDirectDraw2&>(*mpDirectDraw).GetAvailableVidMem( &aSurfaceCaps, &nTotal, &nFree )) )
1625*cdf0e10cSrcweir 				return 0;
1626*cdf0e10cSrcweir 
1627*cdf0e10cSrcweir 			nRes += nFree;
1628*cdf0e10cSrcweir 
1629*cdf0e10cSrcweir 			if( bWithAGPMem )
1630*cdf0e10cSrcweir 			{
1631*cdf0e10cSrcweir 				// AGP RAM (const_cast, since GetAvailableVidMem is non-const)
1632*cdf0e10cSrcweir 				aSurfaceCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM;
1633*cdf0e10cSrcweir 				if( FAILED(const_cast<IDirectDraw2&>(*mpDirectDraw).GetAvailableVidMem( &aSurfaceCaps, &nTotal, &nFree )) )
1634*cdf0e10cSrcweir 					return 0;
1635*cdf0e10cSrcweir 
1636*cdf0e10cSrcweir 				nRes += nFree;
1637*cdf0e10cSrcweir 			}
1638*cdf0e10cSrcweir 
1639*cdf0e10cSrcweir 			// TODO(F1): Add pool mem
1640*cdf0e10cSrcweir 
1641*cdf0e10cSrcweir 			return nRes;
1642*cdf0e10cSrcweir 		}
1643*cdf0e10cSrcweir 
1644*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1645*cdf0e10cSrcweir 		// DXRenderModule::convert2Screen
1646*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1647*cdf0e10cSrcweir 
1648*cdf0e10cSrcweir 		void DXRenderModule::convert2Screen( ::basegfx::B2IPoint& io_rDestPos,
1649*cdf0e10cSrcweir 											 ::basegfx::B2IRange& io_rDestArea )
1650*cdf0e10cSrcweir 		{
1651*cdf0e10cSrcweir 			POINT aPoint = { 0, 0 };
1652*cdf0e10cSrcweir 			ClientToScreen( mhWnd, &aPoint );
1653*cdf0e10cSrcweir 
1654*cdf0e10cSrcweir             // i52230 make sure given screen coordinate is relative to
1655*cdf0e10cSrcweir             // this monitor's area (the device rendering is always
1656*cdf0e10cSrcweir             // contained to a single monitor)
1657*cdf0e10cSrcweir             aPoint.x -= maMonitorInfo.rcMonitor.left;
1658*cdf0e10cSrcweir             aPoint.y -= maMonitorInfo.rcMonitor.top;
1659*cdf0e10cSrcweir 
1660*cdf0e10cSrcweir 			io_rDestPos.setX( io_rDestPos.getX() + aPoint.x );
1661*cdf0e10cSrcweir 			io_rDestPos.setY( io_rDestPos.getY() + aPoint.y );
1662*cdf0e10cSrcweir 
1663*cdf0e10cSrcweir 			const ::basegfx::B2ISize& rSize( getFramebufferSize() );
1664*cdf0e10cSrcweir 
1665*cdf0e10cSrcweir 			// calc output bounds (clip against framebuffer bounds)
1666*cdf0e10cSrcweir 			io_rDestArea = ::basegfx::B2IRange(
1667*cdf0e10cSrcweir 				::std::max( sal_Int32(0),
1668*cdf0e10cSrcweir 							::std::min( sal_Int32(rSize.getX()),
1669*cdf0e10cSrcweir                                         sal_Int32(io_rDestArea.getMinX() + aPoint.x) ) ),
1670*cdf0e10cSrcweir 				::std::max( sal_Int32(0),
1671*cdf0e10cSrcweir 							::std::min( sal_Int32(rSize.getY()),
1672*cdf0e10cSrcweir 										sal_Int32(io_rDestArea.getMinY() + aPoint.y) ) ),
1673*cdf0e10cSrcweir 				::std::max( sal_Int32(0),
1674*cdf0e10cSrcweir 							::std::min( sal_Int32(rSize.getX()),
1675*cdf0e10cSrcweir 										sal_Int32(io_rDestArea.getMaxX() + aPoint.x) ) ),
1676*cdf0e10cSrcweir 				::std::max( sal_Int32(0),
1677*cdf0e10cSrcweir 							::std::min( sal_Int32(rSize.getY()),
1678*cdf0e10cSrcweir 										sal_Int32(io_rDestArea.getMaxY() + aPoint.y) ) ) );
1679*cdf0e10cSrcweir 		}
1680*cdf0e10cSrcweir 
1681*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1682*cdf0e10cSrcweir 		// DXRenderModule::createSystemMemorySurface
1683*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1684*cdf0e10cSrcweir 
1685*cdf0e10cSrcweir 		COMReference<IDirectDrawSurface> DXRenderModule::createSystemMemorySurface( const ::basegfx::B2IVector& rSize )
1686*cdf0e10cSrcweir 		{
1687*cdf0e10cSrcweir 			DDSURFACEDESC 		aSurfaceDesc;
1688*cdf0e10cSrcweir 			IDirectDrawSurface* pSurface;
1689*cdf0e10cSrcweir 
1690*cdf0e10cSrcweir 			aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
1691*cdf0e10cSrcweir 			aSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;;
1692*cdf0e10cSrcweir 			aSurfaceDesc.dwWidth = rSize.getX();
1693*cdf0e10cSrcweir 			aSurfaceDesc.dwHeight= rSize.getY();
1694*cdf0e10cSrcweir 
1695*cdf0e10cSrcweir 			rtl_copyMemory( &aSurfaceDesc.ddpfPixelFormat, &maTextureFormat, sizeof(DDPIXELFORMAT) );
1696*cdf0e10cSrcweir 
1697*cdf0e10cSrcweir 			aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
1698*cdf0e10cSrcweir 
1699*cdf0e10cSrcweir 			HRESULT nRes = mpDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
1700*cdf0e10cSrcweir 			if(FAILED(nRes))
1701*cdf0e10cSrcweir 				return COMReference<IDirectDrawSurface>(NULL);
1702*cdf0e10cSrcweir 
1703*cdf0e10cSrcweir 			return COMReference<IDirectDrawSurface>(pSurface);
1704*cdf0e10cSrcweir 		}
1705*cdf0e10cSrcweir 
1706*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1707*cdf0e10cSrcweir 		// DXRenderModule::flip
1708*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1709*cdf0e10cSrcweir 
1710*cdf0e10cSrcweir 		bool DXRenderModule::flip( const ::basegfx::B2IRectangle& rUpdateArea,
1711*cdf0e10cSrcweir 								   const ::basegfx::B2IRectangle& rCurrWindowArea )
1712*cdf0e10cSrcweir 		{
1713*cdf0e10cSrcweir             // TODO(P2): get rid of those fine-grained locking
1714*cdf0e10cSrcweir 			::osl::MutexGuard aGuard( maMutex );
1715*cdf0e10cSrcweir 
1716*cdf0e10cSrcweir 			// see if the main surfaces got lost. if so, try to
1717*cdf0e10cSrcweir 			// restore them. bail out if this operation fails.
1718*cdf0e10cSrcweir 			if(!(validateMainSurfaces()))
1719*cdf0e10cSrcweir 				return false;
1720*cdf0e10cSrcweir 
1721*cdf0e10cSrcweir 			flushVertexCache();
1722*cdf0e10cSrcweir 
1723*cdf0e10cSrcweir 			ENSURE_OR_THROW( !mnBeginSceneCount,
1724*cdf0e10cSrcweir                               "Device::flip(): within 3D scene" );
1725*cdf0e10cSrcweir 
1726*cdf0e10cSrcweir 			// TODO(E3): handle DX errors more thoroughly. For fullscreen
1727*cdf0e10cSrcweir 			// exclusive mode, actually even our primary surface can get
1728*cdf0e10cSrcweir 			// lost and needs restore!
1729*cdf0e10cSrcweir 
1730*cdf0e10cSrcweir 			if( mpDirectDraw.is() &&
1731*cdf0e10cSrcweir 				mpPrimarySurface.is() &&
1732*cdf0e10cSrcweir 				mpBackBufferSurface.is() )
1733*cdf0e10cSrcweir 			{
1734*cdf0e10cSrcweir 				// ignore area and offset for page flipping device
1735*cdf0e10cSrcweir 				if( mbPageFlipping )
1736*cdf0e10cSrcweir 				{
1737*cdf0e10cSrcweir #if defined(VERBOSE) && defined(DBG_UTIL)
1738*cdf0e10cSrcweir 					renderFPSCounter();
1739*cdf0e10cSrcweir 					renderMemAvailable();
1740*cdf0e10cSrcweir #endif
1741*cdf0e10cSrcweir 					VERBOSE_TRACE( "Device::flip(): Using true page flipping" );
1742*cdf0e10cSrcweir 
1743*cdf0e10cSrcweir 					// use true page flipping. Hopefully, the 3D hardware
1744*cdf0e10cSrcweir 					// is flushed on this flip call (rumours have it that
1745*cdf0e10cSrcweir 					// way), otherwise, perform the Lock hack as for the
1746*cdf0e10cSrcweir 					// Blt below.
1747*cdf0e10cSrcweir 					if( SUCCEEDED(mpPrimarySurface->Flip( NULL, DDFLIP_WAIT )) )
1748*cdf0e10cSrcweir 						return true;
1749*cdf0e10cSrcweir 				}
1750*cdf0e10cSrcweir 				else
1751*cdf0e10cSrcweir 				{
1752*cdf0e10cSrcweir 					VERBOSE_TRACE( "Device::flip(): Using blt for page flipping" );
1753*cdf0e10cSrcweir 
1754*cdf0e10cSrcweir 					// determine actual window position
1755*cdf0e10cSrcweir 					::basegfx::B2IPoint aDestPoint( rUpdateArea.getMinimum() );
1756*cdf0e10cSrcweir 					::basegfx::B2IRange aSourceArea( rUpdateArea );
1757*cdf0e10cSrcweir 					::basegfx::B2IRange aDestArea( 0,0,
1758*cdf0e10cSrcweir                                                    static_cast<sal_Int32>(rCurrWindowArea.getWidth()),
1759*cdf0e10cSrcweir                                                    static_cast<sal_Int32>(rCurrWindowArea.getHeight()) );
1760*cdf0e10cSrcweir 					convert2Screen( aDestPoint, aDestArea );
1761*cdf0e10cSrcweir 
1762*cdf0e10cSrcweir 					// perform clipping
1763*cdf0e10cSrcweir 					if( !::canvas::tools::clipBlit( aSourceArea,
1764*cdf0e10cSrcweir 													aDestPoint,
1765*cdf0e10cSrcweir 													rUpdateArea,
1766*cdf0e10cSrcweir 													aDestArea ) )
1767*cdf0e10cSrcweir 						return true; // fully clipped, but still, in a way,
1768*cdf0e10cSrcweir 									 // successful.
1769*cdf0e10cSrcweir 
1770*cdf0e10cSrcweir 					// TODO(P1): Rumours have it that the 3D hardware
1771*cdf0e10cSrcweir 					// _might_ still be rendering with flaky drivers,
1772*cdf0e10cSrcweir 					// which don't flush properly on Blt(). It was said,
1773*cdf0e10cSrcweir 					// that 'usually', it works to lock the 3D render
1774*cdf0e10cSrcweir 					// target (the backbuffer in this case). OTOH, I've
1775*cdf0e10cSrcweir 					// found that this tends to degrade performance
1776*cdf0e10cSrcweir 					// significantly on complying cards...
1777*cdf0e10cSrcweir 
1778*cdf0e10cSrcweir 					// TODO(P1): Up until rev. 1.3, this method contained
1779*cdf0e10cSrcweir 					// code to make sure the blit will start _immediately_
1780*cdf0e10cSrcweir 					// after the Blt call. If this is not warranted, wait
1781*cdf0e10cSrcweir 					// for the next vsync. As this case was found to be
1782*cdf0e10cSrcweir 					// extremely seldom, kicked out (what's more, there's
1783*cdf0e10cSrcweir 					// simply no guarantee that the blitter will be
1784*cdf0e10cSrcweir 					// available at any point in the code - Windows still
1785*cdf0e10cSrcweir 					// is a preemptive multi-processing environment. And
1786*cdf0e10cSrcweir 					// _if_ we're competing with someone over the blitter,
1787*cdf0e10cSrcweir 					// we will do so the next VBLANK interval, and the
1788*cdf0e10cSrcweir 					// following...)
1789*cdf0e10cSrcweir 
1790*cdf0e10cSrcweir                     // screen update seems to be smoother when waiting
1791*cdf0e10cSrcweir                     // for vblank in every case - even when blitter
1792*cdf0e10cSrcweir                     // supports the DDBLTFX_NOTEARING flag.
1793*cdf0e10cSrcweir                     if( FAILED(mpDirectDraw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,
1794*cdf0e10cSrcweir                                                                   NULL)) )
1795*cdf0e10cSrcweir                         return false;
1796*cdf0e10cSrcweir 
1797*cdf0e10cSrcweir 					DDBLTFX  aBltFx;
1798*cdf0e10cSrcweir 					DDBLTFX* pBltFX = NULL;
1799*cdf0e10cSrcweir 					if( mbHasNoTearingBlt )
1800*cdf0e10cSrcweir 					{
1801*cdf0e10cSrcweir 						// Blt can internally schedule for no-tearing
1802*cdf0e10cSrcweir 						// ===========================================
1803*cdf0e10cSrcweir 
1804*cdf0e10cSrcweir 						rtl_fillMemory( &aBltFx,
1805*cdf0e10cSrcweir 										sizeof(aBltFx), 0 );
1806*cdf0e10cSrcweir 						aBltFx.dwSize = sizeof(aBltFx);
1807*cdf0e10cSrcweir 						aBltFx.dwDDFX = DDBLTFX_NOTEARING;
1808*cdf0e10cSrcweir 
1809*cdf0e10cSrcweir 						pBltFX = &aBltFx;
1810*cdf0e10cSrcweir 					}
1811*cdf0e10cSrcweir 
1812*cdf0e10cSrcweir 					if( doBlit( aDestPoint,
1813*cdf0e10cSrcweir                                 *mpPrimarySurface,
1814*cdf0e10cSrcweir                                 aSourceArea,
1815*cdf0e10cSrcweir                                 *mpBackBufferSurface,
1816*cdf0e10cSrcweir                                 pBltFX,false ) )
1817*cdf0e10cSrcweir 					{
1818*cdf0e10cSrcweir #if defined(VERBOSE) && defined(DBG_UTIL)
1819*cdf0e10cSrcweir 						renderFPSCounter();
1820*cdf0e10cSrcweir 						renderMemAvailable();
1821*cdf0e10cSrcweir #endif
1822*cdf0e10cSrcweir 						return true;
1823*cdf0e10cSrcweir 					}
1824*cdf0e10cSrcweir 				}
1825*cdf0e10cSrcweir 			}
1826*cdf0e10cSrcweir 			return false;
1827*cdf0e10cSrcweir 		}
1828*cdf0e10cSrcweir 
1829*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1830*cdf0e10cSrcweir 		// DXRenderModule::disposing
1831*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1832*cdf0e10cSrcweir 
1833*cdf0e10cSrcweir 		void DXRenderModule::disposing()
1834*cdf0e10cSrcweir 		{
1835*cdf0e10cSrcweir 			if(!(mhWnd))
1836*cdf0e10cSrcweir 				return;
1837*cdf0e10cSrcweir 
1838*cdf0e10cSrcweir 			mpTexture.reset();
1839*cdf0e10cSrcweir 			mpWindow.reset();
1840*cdf0e10cSrcweir 			mhWnd=NULL;
1841*cdf0e10cSrcweir 
1842*cdf0e10cSrcweir             // refrain from releasing the DX5 objects - deleting the
1843*cdf0e10cSrcweir             // DX5 device seems to kill the whole engine, including
1844*cdf0e10cSrcweir             // all objects we might still hold references to
1845*cdf0e10cSrcweir             // (surfaces, e.g.)
1846*cdf0e10cSrcweir 		}
1847*cdf0e10cSrcweir 
1848*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1849*cdf0e10cSrcweir 		// DXRenderModule::screenshot
1850*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1851*cdf0e10cSrcweir 
1852*cdf0e10cSrcweir 		void DXRenderModule::screenShot()
1853*cdf0e10cSrcweir 		{
1854*cdf0e10cSrcweir 			if(!(mpBackBufferSurface.get()))
1855*cdf0e10cSrcweir 				return;
1856*cdf0e10cSrcweir 			char filename[256];
1857*cdf0e10cSrcweir 			static sal_uInt32 counter = 0;
1858*cdf0e10cSrcweir 			sprintf(filename,"c:\\shot%d.bmp",counter++);
1859*cdf0e10cSrcweir 			dumpSurface(mpBackBufferSurface,filename);
1860*cdf0e10cSrcweir 		}
1861*cdf0e10cSrcweir 
1862*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1863*cdf0e10cSrcweir 		// DXRenderModule::validateMainSurfaces
1864*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1865*cdf0e10cSrcweir 
1866*cdf0e10cSrcweir 		bool DXRenderModule::validateMainSurfaces()
1867*cdf0e10cSrcweir 		{
1868*cdf0e10cSrcweir 			if(mpPrimarySurface.get()) {
1869*cdf0e10cSrcweir 				if(mpPrimarySurface->IsLost() == DDERR_SURFACELOST) {
1870*cdf0e10cSrcweir 					if(FAILED(mpPrimarySurface->Restore()))
1871*cdf0e10cSrcweir 						return false;
1872*cdf0e10cSrcweir 				}
1873*cdf0e10cSrcweir 			}
1874*cdf0e10cSrcweir 
1875*cdf0e10cSrcweir 			if(mpBackBufferSurface.get()) {
1876*cdf0e10cSrcweir 				if(mpBackBufferSurface->IsLost() == DDERR_SURFACELOST)
1877*cdf0e10cSrcweir                 {
1878*cdf0e10cSrcweir 					// TODO(F1): simply restoring the backbuffer does not
1879*cdf0e10cSrcweir 					// work as expected, we need to re-create everything
1880*cdf0e10cSrcweir 					// from scratch. find out why...
1881*cdf0e10cSrcweir 					//if(SUCCEEDED(mpBackBufferSurface->Restore()))
1882*cdf0e10cSrcweir 					//	return setup3DDevice();
1883*cdf0e10cSrcweir 
1884*cdf0e10cSrcweir 					mpBackBufferSurface.reset();
1885*cdf0e10cSrcweir 
1886*cdf0e10cSrcweir 					// get us a backbuffer for simulated flipping
1887*cdf0e10cSrcweir 					IDirectDrawSurface* pSurface;
1888*cdf0e10cSrcweir 
1889*cdf0e10cSrcweir 					// TODO(P2): Strictly speaking, we don't need a full screen worth of
1890*cdf0e10cSrcweir 					// backbuffer here. We could also scale dynamically with the current
1891*cdf0e10cSrcweir 					// window size, but this will make it necessary to temporarily have two
1892*cdf0e10cSrcweir 					// buffers while copying from the old to the new one. YMMV.
1893*cdf0e10cSrcweir 					const ::basegfx::B2ISize aSize( getFramebufferSize() );
1894*cdf0e10cSrcweir 
1895*cdf0e10cSrcweir 					DDSURFACEDESC aSurfaceDesc;
1896*cdf0e10cSrcweir 					rtl_fillMemory( &aSurfaceDesc, sizeof(DDSURFACEDESC), 0 );
1897*cdf0e10cSrcweir 					aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
1898*cdf0e10cSrcweir 					aSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1899*cdf0e10cSrcweir 					aSurfaceDesc.dwHeight= aSize.getY();
1900*cdf0e10cSrcweir 					aSurfaceDesc.dwWidth = aSize.getX();
1901*cdf0e10cSrcweir 
1902*cdf0e10cSrcweir 					aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
1903*cdf0e10cSrcweir 
1904*cdf0e10cSrcweir 					HRESULT nRes = mpDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
1905*cdf0e10cSrcweir 
1906*cdf0e10cSrcweir 					if( FAILED( nRes ) )
1907*cdf0e10cSrcweir 					{
1908*cdf0e10cSrcweir 						if( nRes == DDERR_OUTOFVIDEOMEMORY )
1909*cdf0e10cSrcweir 						{
1910*cdf0e10cSrcweir 							// local vid mem failed. Maybe AGP mem works?
1911*cdf0e10cSrcweir 							aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM;
1912*cdf0e10cSrcweir 							if( FAILED(mpDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL)) )
1913*cdf0e10cSrcweir 							{
1914*cdf0e10cSrcweir 								// no chance
1915*cdf0e10cSrcweir 								return false;
1916*cdf0e10cSrcweir 							}
1917*cdf0e10cSrcweir 
1918*cdf0e10cSrcweir 							VERBOSE_TRACE( "Device::Device(): CreateSurface for backbuffer reverted to non-local video mem" );
1919*cdf0e10cSrcweir 						}
1920*cdf0e10cSrcweir 						else
1921*cdf0e10cSrcweir 						{
1922*cdf0e10cSrcweir 							// no chance
1923*cdf0e10cSrcweir 							VERBOSE_TRACE( "Device::Device(): CreateSurface for backbuffer failed" );
1924*cdf0e10cSrcweir 							return false;
1925*cdf0e10cSrcweir 						}
1926*cdf0e10cSrcweir 					}
1927*cdf0e10cSrcweir 
1928*cdf0e10cSrcweir 					VERBOSE_TRACE( "Device::Device(): created backbuffer of size %d times %d pixel",
1929*cdf0e10cSrcweir                                    aSurfaceDesc.dwWidth,
1930*cdf0e10cSrcweir                                    aSurfaceDesc.dwHeight );
1931*cdf0e10cSrcweir 
1932*cdf0e10cSrcweir 					mpBackBufferSurface = COMReference< IDirectDrawSurface >(pSurface);
1933*cdf0e10cSrcweir 
1934*cdf0e10cSrcweir 					return setup3DDevice();
1935*cdf0e10cSrcweir 				}
1936*cdf0e10cSrcweir 			}
1937*cdf0e10cSrcweir 
1938*cdf0e10cSrcweir 			return true;
1939*cdf0e10cSrcweir 		}
1940*cdf0e10cSrcweir 
1941*cdf0e10cSrcweir         void DXRenderModule::renderInfoText( const ::rtl::OUString& rStr,
1942*cdf0e10cSrcweir                                              const Gdiplus::PointF& rPos ) const
1943*cdf0e10cSrcweir         {
1944*cdf0e10cSrcweir             ENSURE_OR_THROW( !mnBeginSceneCount,
1945*cdf0e10cSrcweir                               "Device::renderInfoText(): within 3D scene" );
1946*cdf0e10cSrcweir 
1947*cdf0e10cSrcweir             // render text directly to primary surface
1948*cdf0e10cSrcweir             GraphicsSharedPtr pGraphics;
1949*cdf0e10cSrcweir 
1950*cdf0e10cSrcweir             if( mbPageFlipping )
1951*cdf0e10cSrcweir             {
1952*cdf0e10cSrcweir                 // render on top of backbuffer. We have
1953*cdf0e10cSrcweir                 // page flipping, anyway, thus this will
1954*cdf0e10cSrcweir                 // cost us nothing.
1955*cdf0e10cSrcweir                 pGraphics = createSurfaceGraphics( mpBackBufferSurface );
1956*cdf0e10cSrcweir             }
1957*cdf0e10cSrcweir             else
1958*cdf0e10cSrcweir             {
1959*cdf0e10cSrcweir                 // render FPS directly to front buffer.
1960*cdf0e10cSrcweir                 // That saves us another explicit blit,
1961*cdf0e10cSrcweir                 // and for me, the FPS counter can blink,
1962*cdf0e10cSrcweir                 // if it likes to...
1963*cdf0e10cSrcweir                 pGraphics = createSurfaceGraphics( mpPrimarySurface );
1964*cdf0e10cSrcweir             }
1965*cdf0e10cSrcweir 
1966*cdf0e10cSrcweir             if( !mbPageFlipping )
1967*cdf0e10cSrcweir             {
1968*cdf0e10cSrcweir                 // clear background. We might be doing optimized redraws,
1969*cdf0e10cSrcweir                 // and the background under the FPS count will then not be
1970*cdf0e10cSrcweir                 // cleared.
1971*cdf0e10cSrcweir                 Gdiplus::SolidBrush aBrush(
1972*cdf0e10cSrcweir                     Gdiplus::Color( 255, 255, 255 ) );
1973*cdf0e10cSrcweir 
1974*cdf0e10cSrcweir                 pGraphics->FillRectangle( &aBrush,
1975*cdf0e10cSrcweir                                           rPos.X, rPos.Y, 80.0, 20.0 );
1976*cdf0e10cSrcweir             }
1977*cdf0e10cSrcweir 
1978*cdf0e10cSrcweir             Gdiplus::SolidBrush aBrush(
1979*cdf0e10cSrcweir                 Gdiplus::Color( 255, 0, 255 ) );
1980*cdf0e10cSrcweir             Gdiplus::Font aFont( NULL,
1981*cdf0e10cSrcweir                                  16,
1982*cdf0e10cSrcweir                                  Gdiplus::FontStyleRegular,
1983*cdf0e10cSrcweir                                  Gdiplus::UnitWorld,
1984*cdf0e10cSrcweir                                  NULL );
1985*cdf0e10cSrcweir             pGraphics->DrawString( reinterpret_cast<LPCWSTR>(rStr.getStr()),
1986*cdf0e10cSrcweir                                    rStr.getLength(),
1987*cdf0e10cSrcweir                                    &aFont,
1988*cdf0e10cSrcweir                                    rPos,
1989*cdf0e10cSrcweir                                    &aBrush );
1990*cdf0e10cSrcweir         }
1991*cdf0e10cSrcweir 
1992*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1993*cdf0e10cSrcweir 		// DXRenderModule::renderMemAvailable
1994*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
1995*cdf0e10cSrcweir 
1996*cdf0e10cSrcweir 		void DXRenderModule::renderMemAvailable() const
1997*cdf0e10cSrcweir 		{
1998*cdf0e10cSrcweir 			ENSURE_OR_THROW( !mnBeginSceneCount,
1999*cdf0e10cSrcweir                               "DXRenderModule::renderMemAvailable(): within 3D scene" );
2000*cdf0e10cSrcweir 
2001*cdf0e10cSrcweir 			const double nSurfaceMem( getAvailableSurfaceMem()/1024 );
2002*cdf0e10cSrcweir 
2003*cdf0e10cSrcweir 			::rtl::OUString text( ::rtl::math::doubleToUString( nSurfaceMem,
2004*cdf0e10cSrcweir 																rtl_math_StringFormat_F,
2005*cdf0e10cSrcweir 																2,'.',NULL,' ') );
2006*cdf0e10cSrcweir 
2007*cdf0e10cSrcweir 			// pad with leading space
2008*cdf0e10cSrcweir 			while( text.getLength() < 6 )
2009*cdf0e10cSrcweir 				text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" ")) + text;
2010*cdf0e10cSrcweir 
2011*cdf0e10cSrcweir 			text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("S: ")) + text;
2012*cdf0e10cSrcweir 
2013*cdf0e10cSrcweir 			renderInfoText( text,
2014*cdf0e10cSrcweir 							Gdiplus::PointF( 0.0, 20) );
2015*cdf0e10cSrcweir 
2016*cdf0e10cSrcweir 
2017*cdf0e10cSrcweir 			const double nTexMem( getAvailableTextureMem()/1024 );
2018*cdf0e10cSrcweir 
2019*cdf0e10cSrcweir 			text = ::rtl::math::doubleToUString( nTexMem,
2020*cdf0e10cSrcweir 												rtl_math_StringFormat_F,
2021*cdf0e10cSrcweir 												2,'.',NULL,' ');
2022*cdf0e10cSrcweir 			// pad with leading space
2023*cdf0e10cSrcweir 			while( text.getLength() < 6 )
2024*cdf0e10cSrcweir 				text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" ")) + text;
2025*cdf0e10cSrcweir 
2026*cdf0e10cSrcweir 			text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("T: ")) + text;
2027*cdf0e10cSrcweir 
2028*cdf0e10cSrcweir 			renderInfoText( text,
2029*cdf0e10cSrcweir 							Gdiplus::PointF( 0.0, 40) );
2030*cdf0e10cSrcweir 
2031*cdf0e10cSrcweir 			VERBOSE_TRACE( "dxcanvas: %f free surface mem, %f free texture mem",
2032*cdf0e10cSrcweir                            nSurfaceMem, nTexMem );
2033*cdf0e10cSrcweir 		}
2034*cdf0e10cSrcweir 
2035*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
2036*cdf0e10cSrcweir 		// DXRenderModule::renderFPSCounter
2037*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
2038*cdf0e10cSrcweir 
2039*cdf0e10cSrcweir 		void DXRenderModule::renderFPSCounter() const
2040*cdf0e10cSrcweir 		{
2041*cdf0e10cSrcweir 			ENSURE_OR_THROW( !mnBeginSceneCount,
2042*cdf0e10cSrcweir                               "DXRenderModule::ren    derFPSCounter(): within 3D scene" );
2043*cdf0e10cSrcweir 
2044*cdf0e10cSrcweir 			const double denominator( maLastUpdate.getElapsedTime() );
2045*cdf0e10cSrcweir 			maLastUpdate.reset();
2046*cdf0e10cSrcweir 
2047*cdf0e10cSrcweir 			::rtl::OUString text( ::rtl::math::doubleToUString( denominator == 0.0 ? 100.0 : 1.0/denominator,
2048*cdf0e10cSrcweir 																rtl_math_StringFormat_F,
2049*cdf0e10cSrcweir 																2,'.',NULL,' ') );
2050*cdf0e10cSrcweir 
2051*cdf0e10cSrcweir 			// pad with leading space
2052*cdf0e10cSrcweir 			while( text.getLength() < 6 )
2053*cdf0e10cSrcweir 				text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" ")) + text;
2054*cdf0e10cSrcweir 
2055*cdf0e10cSrcweir 			text += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" fps"));
2056*cdf0e10cSrcweir 
2057*cdf0e10cSrcweir 			renderInfoText( text,
2058*cdf0e10cSrcweir 							Gdiplus::PointF() );
2059*cdf0e10cSrcweir 
2060*cdf0e10cSrcweir 			VERBOSE_TRACE( "dxcanvas: %f FPS",
2061*cdf0e10cSrcweir                            denominator == 0.0 ? 100.0 : 1.0/denominator );
2062*cdf0e10cSrcweir 		}
2063*cdf0e10cSrcweir 
2064*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
2065*cdf0e10cSrcweir 		// DXRenderModule::resize
2066*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
2067*cdf0e10cSrcweir 
2068*cdf0e10cSrcweir 		void DXRenderModule::resize( const ::basegfx::B2IRange& rect )
2069*cdf0e10cSrcweir 		{
2070*cdf0e10cSrcweir             // TODO(P2): get rid of those fine-grained locking
2071*cdf0e10cSrcweir 			::osl::MutexGuard aGuard( maMutex );
2072*cdf0e10cSrcweir 
2073*cdf0e10cSrcweir 			if( mhWnd==0 )
2074*cdf0e10cSrcweir 				return;
2075*cdf0e10cSrcweir 
2076*cdf0e10cSrcweir 			// don't do anything if the size didn't change.
2077*cdf0e10cSrcweir 			if(maSize.getX() == static_cast<sal_Int32>(rect.getWidth()) &&
2078*cdf0e10cSrcweir 			   maSize.getY() == static_cast<sal_Int32>(rect.getHeight()))
2079*cdf0e10cSrcweir 			   return;
2080*cdf0e10cSrcweir 
2081*cdf0e10cSrcweir 			// TODO(Q2): use numeric cast to prevent overflow
2082*cdf0e10cSrcweir 			maSize.setX(static_cast<sal_Int32>(rect.getWidth()));
2083*cdf0e10cSrcweir 			maSize.setY(static_cast<sal_Int32>(rect.getHeight()));
2084*cdf0e10cSrcweir 
2085*cdf0e10cSrcweir 			mpWindow->SetPosSizePixel(0,0,maSize.getX(),maSize.getY());
2086*cdf0e10cSrcweir 		}
2087*cdf0e10cSrcweir 
2088*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
2089*cdf0e10cSrcweir 		// DXRenderModule::getPageSize
2090*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////////
2091*cdf0e10cSrcweir 
2092*cdf0e10cSrcweir 		::basegfx::B2IVector DXRenderModule::getPageSize()
2093*cdf0e10cSrcweir 		{
2094*cdf0e10cSrcweir             // TODO(P2): get rid of those fine-grained locking
2095*cdf0e10cSrcweir 			::osl::MutexGuard aGuard( maMutex );
2096*cdf0e10cSrcweir 			return maPageSize;
2097*cdf0e10cSrcweir 		}
2098*cdf0e10cSrcweir 
2099*cdf0e10cSrcweir 		::canvas::ISurfaceSharedPtr DXRenderModule::createSurface( const ::basegfx::B2IVector& surfaceSize )
2100*cdf0e10cSrcweir 		{
2101*cdf0e10cSrcweir             // TODO(P2): get rid of those fine-grained locking
2102*cdf0e10cSrcweir 			::osl::MutexGuard aGuard( maMutex );
2103*cdf0e10cSrcweir 
2104*cdf0e10cSrcweir 			const ::basegfx::B2IVector& rPageSize( getPageSize() );
2105*cdf0e10cSrcweir 			::basegfx::B2ISize aSize(surfaceSize);
2106*cdf0e10cSrcweir 			if(!(aSize.getX()))
2107*cdf0e10cSrcweir 				aSize.setX(rPageSize.getX());
2108*cdf0e10cSrcweir 			if(!(aSize.getY()))
2109*cdf0e10cSrcweir 				aSize.setY(rPageSize.getY());
2110*cdf0e10cSrcweir 
2111*cdf0e10cSrcweir 			if(mpTexture.use_count() == 1)
2112*cdf0e10cSrcweir 				return mpTexture;
2113*cdf0e10cSrcweir 
2114*cdf0e10cSrcweir 			return ::canvas::ISurfaceSharedPtr(
2115*cdf0e10cSrcweir 				new DXSurface(*this,
2116*cdf0e10cSrcweir                               aSize) );
2117*cdf0e10cSrcweir 		}
2118*cdf0e10cSrcweir 
2119*cdf0e10cSrcweir 		void DXRenderModule::beginPrimitive( PrimitiveType eType )
2120*cdf0e10cSrcweir 		{
2121*cdf0e10cSrcweir             // TODO(P2): get rid of those fine-grained locking
2122*cdf0e10cSrcweir 			::osl::MutexGuard aGuard( maMutex );
2123*cdf0e10cSrcweir 
2124*cdf0e10cSrcweir 			ENSURE_OR_THROW( !mnBeginSceneCount,
2125*cdf0e10cSrcweir                               "DXRenderModule::beginPrimitive(): nested call" );
2126*cdf0e10cSrcweir 
2127*cdf0e10cSrcweir 			++mnBeginSceneCount;
2128*cdf0e10cSrcweir 			meType=eType;
2129*cdf0e10cSrcweir 			mnCount=0;
2130*cdf0e10cSrcweir 		}
2131*cdf0e10cSrcweir 
2132*cdf0e10cSrcweir 		void DXRenderModule::endPrimitive()
2133*cdf0e10cSrcweir 		{
2134*cdf0e10cSrcweir             // TODO(P2): get rid of those fine-grained locking
2135*cdf0e10cSrcweir 			::osl::MutexGuard aGuard( maMutex );
2136*cdf0e10cSrcweir 
2137*cdf0e10cSrcweir 			--mnBeginSceneCount;
2138*cdf0e10cSrcweir 			meType=PRIMITIVE_TYPE_UNKNOWN;
2139*cdf0e10cSrcweir 			mnCount=0;
2140*cdf0e10cSrcweir 		}
2141*cdf0e10cSrcweir 
2142*cdf0e10cSrcweir 		void DXRenderModule::pushVertex( const ::canvas::Vertex& vertex )
2143*cdf0e10cSrcweir 		{
2144*cdf0e10cSrcweir             // TODO(P2): get rid of those fine-grained locking
2145*cdf0e10cSrcweir 			::osl::MutexGuard aGuard( maMutex );
2146*cdf0e10cSrcweir 
2147*cdf0e10cSrcweir 			switch(meType)
2148*cdf0e10cSrcweir 			{
2149*cdf0e10cSrcweir 				case PRIMITIVE_TYPE_TRIANGLE:
2150*cdf0e10cSrcweir                 {
2151*cdf0e10cSrcweir 					maVertexCache.push_back(vertex);
2152*cdf0e10cSrcweir 					++mnCount;
2153*cdf0e10cSrcweir 					mnCount &= 3;
2154*cdf0e10cSrcweir 					break;
2155*cdf0e10cSrcweir                 }
2156*cdf0e10cSrcweir 
2157*cdf0e10cSrcweir 				case PRIMITIVE_TYPE_QUAD:
2158*cdf0e10cSrcweir                 {
2159*cdf0e10cSrcweir 					if(mnCount == 3)
2160*cdf0e10cSrcweir 					{
2161*cdf0e10cSrcweir 						const std::size_t size(maVertexCache.size());
2162*cdf0e10cSrcweir 						::canvas::Vertex v0(maVertexCache[size-1]);
2163*cdf0e10cSrcweir 						::canvas::Vertex v2(maVertexCache[size-3]);
2164*cdf0e10cSrcweir 						maVertexCache.push_back(v0);
2165*cdf0e10cSrcweir 						maVertexCache.push_back(vertex);
2166*cdf0e10cSrcweir 						maVertexCache.push_back(v2);
2167*cdf0e10cSrcweir 						mnCount=0;
2168*cdf0e10cSrcweir 					}
2169*cdf0e10cSrcweir 					else
2170*cdf0e10cSrcweir 					{
2171*cdf0e10cSrcweir 						maVertexCache.push_back(vertex);
2172*cdf0e10cSrcweir 						++mnCount;
2173*cdf0e10cSrcweir 					}
2174*cdf0e10cSrcweir 					break;
2175*cdf0e10cSrcweir                 }
2176*cdf0e10cSrcweir 
2177*cdf0e10cSrcweir                 default:
2178*cdf0e10cSrcweir                     OSL_ENSURE( false,
2179*cdf0e10cSrcweir                                 "DXRenderModule::pushVertex(): unexpected primitive types" );
2180*cdf0e10cSrcweir                     break;
2181*cdf0e10cSrcweir 			}
2182*cdf0e10cSrcweir 		}
2183*cdf0e10cSrcweir 
2184*cdf0e10cSrcweir 		bool DXRenderModule::isError()
2185*cdf0e10cSrcweir 		{
2186*cdf0e10cSrcweir             // TODO(P2): get rid of those fine-grained locking
2187*cdf0e10cSrcweir 			::osl::MutexGuard aGuard( maMutex );
2188*cdf0e10cSrcweir 
2189*cdf0e10cSrcweir 			return mbError;
2190*cdf0e10cSrcweir 		}
2191*cdf0e10cSrcweir 
2192*cdf0e10cSrcweir 		void DXRenderModule::flushVertexCache()
2193*cdf0e10cSrcweir 		{
2194*cdf0e10cSrcweir 			if(!(maVertexCache.size()))
2195*cdf0e10cSrcweir 				return;
2196*cdf0e10cSrcweir 
2197*cdf0e10cSrcweir 			mbError=true;
2198*cdf0e10cSrcweir 
2199*cdf0e10cSrcweir 			if( FAILED(mpDirect3DDevice->BeginScene()) )
2200*cdf0e10cSrcweir 				return;
2201*cdf0e10cSrcweir 
2202*cdf0e10cSrcweir 			// enable texture alpha blending
2203*cdf0e10cSrcweir 			if( FAILED(mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE,TRUE)))
2204*cdf0e10cSrcweir 				return;
2205*cdf0e10cSrcweir 
2206*cdf0e10cSrcweir 			// enable texture alpha modulation, for honoring fAlpha
2207*cdf0e10cSrcweir 			if( FAILED(mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREMAPBLEND,
2208*cdf0e10cSrcweir 														D3DTBLEND_MODULATEALPHA)) )
2209*cdf0e10cSrcweir 				return;
2210*cdf0e10cSrcweir 
2211*cdf0e10cSrcweir 			// enable texture magnification filtering (don't care if this
2212*cdf0e10cSrcweir 			// fails, it's just visually more pleasant)
2213*cdf0e10cSrcweir 			mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREMAG,
2214*cdf0e10cSrcweir                                              D3DFILTER_LINEAR);
2215*cdf0e10cSrcweir 
2216*cdf0e10cSrcweir 			// enable texture minification filtering (don't care if this
2217*cdf0e10cSrcweir 			// fails, it's just visually more pleasant)
2218*cdf0e10cSrcweir 			mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREMIN,
2219*cdf0e10cSrcweir                                              D3DFILTER_LINEAR);
2220*cdf0e10cSrcweir 
2221*cdf0e10cSrcweir 			// enable subpixel texture output (don't care if this
2222*cdf0e10cSrcweir 			// fails, it's just visually more pleasant)
2223*cdf0e10cSrcweir  			mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_SUBPIXEL,
2224*cdf0e10cSrcweir                                              TRUE);
2225*cdf0e10cSrcweir 
2226*cdf0e10cSrcweir 			// normal combination of object...
2227*cdf0e10cSrcweir 			if( FAILED(mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND,
2228*cdf0e10cSrcweir 														D3DBLEND_SRCALPHA)) )
2229*cdf0e10cSrcweir 				return;
2230*cdf0e10cSrcweir 
2231*cdf0e10cSrcweir 			// ..and background color
2232*cdf0e10cSrcweir 			if( FAILED(mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND,
2233*cdf0e10cSrcweir 														D3DBLEND_INVSRCALPHA)) )
2234*cdf0e10cSrcweir 				return;
2235*cdf0e10cSrcweir 
2236*cdf0e10cSrcweir 			// disable backface culling; this enables us to mirror sprites
2237*cdf0e10cSrcweir 			// by simply reverting the triangles, which, with enabled
2238*cdf0e10cSrcweir 			// culling, would be invisible otherwise
2239*cdf0e10cSrcweir 			if( FAILED(mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE,
2240*cdf0e10cSrcweir 														D3DCULL_NONE)) )
2241*cdf0e10cSrcweir 				return;
2242*cdf0e10cSrcweir 
2243*cdf0e10cSrcweir 			mbError=false;
2244*cdf0e10cSrcweir 
2245*cdf0e10cSrcweir  			const float nHalfPixelSizeX(0.5f/maPageSize.getX());
2246*cdf0e10cSrcweir  			const float nHalfPixelSizeY(0.5f/maPageSize.getY());
2247*cdf0e10cSrcweir 			sal_uInt32 nIndex(0);
2248*cdf0e10cSrcweir 			const std::size_t size(maVertexCache.size());
2249*cdf0e10cSrcweir             D3DTLVERTEX *vertices = static_cast<D3DTLVERTEX *>(_alloca(sizeof(D3DTLVERTEX)*size));
2250*cdf0e10cSrcweir 			vertexCache_t::const_iterator it(maVertexCache.begin());
2251*cdf0e10cSrcweir 			while(it != maVertexCache.end())
2252*cdf0e10cSrcweir 			{
2253*cdf0e10cSrcweir 				vertices[nIndex++] = D3DTLVERTEX(
2254*cdf0e10cSrcweir 					D3DVECTOR(static_cast<D3DVALUE>(it->x),
2255*cdf0e10cSrcweir 							  static_cast<D3DVALUE>(it->y),
2256*cdf0e10cSrcweir 							  static_cast<D3DVALUE>(it->z)),
2257*cdf0e10cSrcweir 					1,
2258*cdf0e10cSrcweir 					D3DRGBA(1,1,1,it->a),
2259*cdf0e10cSrcweir 					D3DRGBA(0,0,0,0),
2260*cdf0e10cSrcweir 					static_cast<float>(it->u + nHalfPixelSizeX),
2261*cdf0e10cSrcweir 					static_cast<float>(it->v + nHalfPixelSizeY));
2262*cdf0e10cSrcweir 				++it;
2263*cdf0e10cSrcweir 			}
2264*cdf0e10cSrcweir 
2265*cdf0e10cSrcweir 			maVertexCache.clear();
2266*cdf0e10cSrcweir 
2267*cdf0e10cSrcweir 			mbError |= FAILED(mpDirect3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
2268*cdf0e10cSrcweir 															  D3DVT_TLVERTEX,
2269*cdf0e10cSrcweir 															  (LPVOID)vertices,
2270*cdf0e10cSrcweir 															  size,
2271*cdf0e10cSrcweir 															  0));
2272*cdf0e10cSrcweir 
2273*cdf0e10cSrcweir 			mbError |= FAILED(mpDirect3DDevice->EndScene());
2274*cdf0e10cSrcweir 		}
2275*cdf0e10cSrcweir 	}
2276*cdf0e10cSrcweir 
2277*cdf0e10cSrcweir 	IDXRenderModuleSharedPtr createRenderModule( const ::Window& rParent )
2278*cdf0e10cSrcweir 	{
2279*cdf0e10cSrcweir 		return IDXRenderModuleSharedPtr( new DXRenderModule(rParent) );
2280*cdf0e10cSrcweir 	}
2281*cdf0e10cSrcweir }
2282*cdf0e10cSrcweir 
2283*cdf0e10cSrcweir #endif
2284