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