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