diff options
author | Kurt Zenker <kz@openoffice.org> | 2008-06-24 09:39:05 +0000 |
---|---|---|
committer | Kurt Zenker <kz@openoffice.org> | 2008-06-24 09:39:05 +0000 |
commit | 9e15933dda54ceb5f016d71495b3932a628623d2 (patch) | |
tree | a73f93e62b8240944d0e90040f277bcb1e4df2aa /canvas/source/directx/dx_surfacebitmap.cxx | |
parent | 3e1314345d87aff337ae101c191e58ca2a6f04d8 (diff) |
INTEGRATION: CWS canvas05 (1.1.2); FILE ADDED
2008/06/03 23:52:24 thb 1.1.2.5: Removed extra level of indirection for getting a graphics for a surface; removed some unused code
2008/06/03 11:11:24 thb 1.1.2.4: Cleaned up image debugging stuff; fixed a few d3d debug warnings; fixed one deadlock rendering a bitmap from the same surface to itself; fixed premature ReleaseDC call in GraphicsProvider::getGraphics()
2008/05/23 22:03:45 thb 1.1.2.3: Moving all remaining new files to LGPL 3
2008/02/08 00:26:39 thb 1.1.2.2: #81092# Finishing cooperative canvas output stuff
2008/01/22 00:25:24 thb 1.1.2.1: #i81092# Making gdiplus and dx canvas more independent
Diffstat (limited to 'canvas/source/directx/dx_surfacebitmap.cxx')
-rw-r--r-- | canvas/source/directx/dx_surfacebitmap.cxx | 807 |
1 files changed, 807 insertions, 0 deletions
diff --git a/canvas/source/directx/dx_surfacebitmap.cxx b/canvas/source/directx/dx_surfacebitmap.cxx new file mode 100644 index 000000000000..e82f814d3b23 --- /dev/null +++ b/canvas/source/directx/dx_surfacebitmap.cxx @@ -0,0 +1,807 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dx_surfacebitmap.cxx,v $ + * $Revision: 1.2 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_canvas.hxx" + +#include "dx_surfacebitmap.hxx" +#include "dx_impltools.hxx" +#include "dx_surfacegraphics.hxx" +#include "dx_graphicsprovider.hxx" + +#include <canvas/debug.hxx> +#include <tools/diagnose_ex.h> + +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/range/b2irange.hxx> + +#if defined(DX_DEBUG_IMAGES) +# if OSL_DEBUG_LEVEL > 0 +# include <imdebug.h> +# undef min +# undef max +# endif +#endif + +using namespace ::com::sun::star; + +namespace dxcanvas +{ + namespace + { + ////////////////////////////////////////////////////////////////////////////////// + // DXColorBuffer + ////////////////////////////////////////////////////////////////////////////////// + + struct DXColorBuffer : public canvas::IColorBuffer + { + public: + DXColorBuffer( const COMReference<surface_type>& rSurface, + const ::basegfx::B2IVector& rSize ) : + mpSurface(rSurface), + maSize(rSize), + mbAlpha(false) + { + } + + // implementation of the 'IColorBuffer' interface + public: + + virtual sal_uInt8* lock() const; + virtual void unlock() const; + virtual sal_uInt32 getWidth() const; + virtual sal_uInt32 getHeight() const; + virtual sal_uInt32 getStride() const; + virtual Format getFormat() const; + + private: + + ::basegfx::B2IVector maSize; +#if DIRECTX_VERSION < 0x0900 + mutable DDSURFACEDESC aSurfaceDesc; +#else + mutable D3DLOCKED_RECT maLockedRect; +#endif + mutable COMReference<surface_type> mpSurface; + bool mbAlpha; + }; + + sal_uInt8* DXColorBuffer::lock() const + { +#if DIRECTX_VERSION < 0x0900 + rtl_fillMemory((void *)&aSurfaceDesc,sizeof(DDSURFACEDESC),0); + aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC); + const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY; + if(SUCCEEDED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL))) + return static_cast<sal_uInt8 *>(aSurfaceDesc.lpSurface); +#else + if(SUCCEEDED(mpSurface->LockRect(&maLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY))) + return static_cast<sal_uInt8 *>(maLockedRect.pBits); +#endif + return NULL; + } + + void DXColorBuffer::unlock() const + { +#if DIRECTX_VERSION < 0x0900 + mpSurface->Unlock(NULL); +#else + mpSurface->UnlockRect(); +#endif + } + + sal_uInt32 DXColorBuffer::getWidth() const + { + return maSize.getX(); + } + + sal_uInt32 DXColorBuffer::getHeight() const + { + return maSize.getY(); + } + + sal_uInt32 DXColorBuffer::getStride() const + { +#if DIRECTX_VERSION < 0x0900 + return aSurfaceDesc.lPitch; +#else + return maLockedRect.Pitch; +#endif + } + + canvas::IColorBuffer::Format DXColorBuffer::getFormat() const + { + return canvas::IColorBuffer::FMT_X8R8G8B8; + } + + ////////////////////////////////////////////////////////////////////////////////// + // GDIColorBuffer + ////////////////////////////////////////////////////////////////////////////////// + + struct GDIColorBuffer : public canvas::IColorBuffer + { + public: + + GDIColorBuffer( const BitmapSharedPtr& rSurface, + const ::basegfx::B2IVector& rSize ) : + mpGDIPlusBitmap(rSurface), + maSize(rSize), + mbAlpha(true) + { + } + + // implementation of the 'IColorBuffer' interface + public: + + virtual sal_uInt8* lock() const; + virtual void unlock() const; + virtual sal_uInt32 getWidth() const; + virtual sal_uInt32 getHeight() const; + virtual sal_uInt32 getStride() const; + virtual Format getFormat() const; + + private: + + ::basegfx::B2IVector maSize; + mutable Gdiplus::BitmapData aBmpData; + BitmapSharedPtr mpGDIPlusBitmap; + bool mbAlpha; + }; + + sal_uInt8* GDIColorBuffer::lock() const + { + aBmpData.Width = maSize.getX(); + aBmpData.Height = maSize.getY(); + aBmpData.Stride = 4*aBmpData.Width; + aBmpData.PixelFormat = PixelFormat32bppARGB; + aBmpData.Scan0 = NULL; + const Gdiplus::Rect aRect( 0,0,aBmpData.Width,aBmpData.Height ); + if( Gdiplus::Ok != mpGDIPlusBitmap->LockBits( &aRect, + Gdiplus::ImageLockModeRead, + PixelFormat32bppARGB, + &aBmpData ) ) + { + return NULL; + } + + return static_cast<sal_uInt8*>(aBmpData.Scan0); + } + + void GDIColorBuffer::unlock() const + { + mpGDIPlusBitmap->UnlockBits( &aBmpData ); + } + + sal_uInt32 GDIColorBuffer::getWidth() const + { + return maSize.getX(); + } + + sal_uInt32 GDIColorBuffer::getHeight() const + { + return maSize.getY(); + } + + sal_uInt32 GDIColorBuffer::getStride() const + { + return aBmpData.Stride; + } + + canvas::IColorBuffer::Format GDIColorBuffer::getFormat() const + { + return canvas::IColorBuffer::FMT_A8R8G8B8; + } + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::DXSurfaceBitmap + ////////////////////////////////////////////////////////////////////////////////// + + DXSurfaceBitmap::DXSurfaceBitmap( const ::basegfx::B2IVector& rSize, + const canvas::ISurfaceProxyManagerSharedPtr& rMgr, + const IDXRenderModuleSharedPtr& rRenderModule, + bool bWithAlpha ) : + mpGdiPlusUser( GDIPlusUser::createInstance() ), + maSize(rSize), + mpRenderModule(rRenderModule), + mpSurfaceManager(rMgr), + mpSurfaceProxy(), + mpSurface(), + mpGDIPlusBitmap(), + mpGraphics(), + mpColorBuffer(), + mbIsSurfaceDirty(true), + mbAlpha(bWithAlpha) + { + init(); + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::getSize + ////////////////////////////////////////////////////////////////////////////////// + + ::basegfx::B2IVector DXSurfaceBitmap::getSize() const + { + return maSize; + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::init + ////////////////////////////////////////////////////////////////////////////////// + + void DXSurfaceBitmap::init() + { + // create container for pixel data + if(mbAlpha) + { + mpGDIPlusBitmap.reset( + new Gdiplus::Bitmap( + maSize.getX(), + maSize.getY(), + PixelFormat32bppARGB + )); + mpGraphics.reset( tools::createGraphicsFromBitmap(mpGDIPlusBitmap) ); + + // create the colorbuffer object, which is basically a simple + // wrapper around the directx surface. the colorbuffer is the + // interface which is used by the surfaceproxy to support any + // kind of underlying structure for the pixel data container. + mpColorBuffer.reset(new GDIColorBuffer(mpGDIPlusBitmap,maSize)); + } + else + { + mpSurface = mpRenderModule->createSystemMemorySurface(maSize); + + // create the colorbuffer object, which is basically a simple + // wrapper around the directx surface. the colorbuffer is the + // interface which is used by the surfaceproxy to support any + // kind of underlying structure for the pixel data container. + mpColorBuffer.reset(new DXColorBuffer(mpSurface,maSize)); + } + + // create a (possibly hardware accelerated) mirror surface. + mpSurfaceProxy = mpSurfaceManager->createSurfaceProxy(mpColorBuffer); + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::resize + ////////////////////////////////////////////////////////////////////////////////// + + bool DXSurfaceBitmap::resize( const ::basegfx::B2IVector& rSize ) + { + if(maSize != rSize) + { + maSize = rSize; + init(); + } + + return true; + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::clear + ////////////////////////////////////////////////////////////////////////////////// + + void DXSurfaceBitmap::clear() + { + GraphicsSharedPtr pGraphics(getGraphics()); + Gdiplus::Color transColor(255,0,0,0); + pGraphics->SetCompositingMode( Gdiplus::CompositingModeSourceCopy ); + pGraphics->Clear( transColor ); + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::hasAlpha + ////////////////////////////////////////////////////////////////////////////////// + + bool DXSurfaceBitmap::hasAlpha() const + { + return mbAlpha; + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::getGraphics + ////////////////////////////////////////////////////////////////////////////////// + + GraphicsSharedPtr DXSurfaceBitmap::getGraphics() + { + // since clients will most probably draw directly + // to the GDI+ bitmap, we need to mark it as dirty + // to ensure that the corrosponding dxsurface will + // be updated. + mbIsSurfaceDirty = true; + + if(hasAlpha()) + return mpGraphics; + else + return createSurfaceGraphics(mpSurface); + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::getBitmap + ////////////////////////////////////////////////////////////////////////////////// + + BitmapSharedPtr DXSurfaceBitmap::getBitmap() const + { + if(hasAlpha()) + return mpGDIPlusBitmap; + + BitmapSharedPtr pResult; + +#if DIRECTX_VERSION < 0x0900 + DDSURFACEDESC aSurfaceDesc; + rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0); + aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC); + const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY; + + // lock the directx surface to receive the pointer to the surface memory. + if(SUCCEEDED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL))) + { + // decide about the format we pass the gdi+, the directx surface is always + // 32bit, either with or without alpha component. + Gdiplus::PixelFormat nFormat = hasAlpha() ? PixelFormat32bppARGB : PixelFormat32bppRGB; + + // construct a gdi+ bitmap from the raw pixel data. + pResult.reset(new Gdiplus::Bitmap( maSize.getX(),maSize.getY(), + aSurfaceDesc.lPitch, + nFormat, + (BYTE *)aSurfaceDesc.lpSurface )); + + // unlock the directx surface + mpSurface->Unlock(NULL); + } +#else + D3DLOCKED_RECT aLockedRect; + if(SUCCEEDED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY))) + { + // decide about the format we pass the gdi+, the directx surface is always + // 32bit, either with or without alpha component. + Gdiplus::PixelFormat nFormat = hasAlpha() ? PixelFormat32bppARGB : PixelFormat32bppRGB; + + // construct a gdi+ bitmap from the raw pixel data. + pResult.reset(new Gdiplus::Bitmap( maSize.getX(),maSize.getY(), + aLockedRect.Pitch, + nFormat, + (BYTE *)aLockedRect.pBits )); + + mpSurface->UnlockRect(); + } +#endif + + return pResult; + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::draw + ////////////////////////////////////////////////////////////////////////////////// + + bool DXSurfaceBitmap::draw( double fAlpha, + const ::basegfx::B2DPoint& rPos, + const ::basegfx::B2DPolyPolygon& rClipPoly, + const ::basegfx::B2DHomMatrix& rTransform ) + { + if( mbIsSurfaceDirty ) + { + mpSurfaceProxy->setColorBufferDirty(); + mbIsSurfaceDirty = false; + } + + return mpSurfaceProxy->draw( fAlpha, rPos, rClipPoly, rTransform ); + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::draw + ////////////////////////////////////////////////////////////////////////////////// + + bool DXSurfaceBitmap::draw( double fAlpha, + const ::basegfx::B2DPoint& rPos, + const ::basegfx::B2DRange& rArea, + const ::basegfx::B2DHomMatrix& rTransform ) + { + if( mbIsSurfaceDirty ) + { + mpSurfaceProxy->setColorBufferDirty(); + mbIsSurfaceDirty = false; + } + + return mpSurfaceProxy->draw( fAlpha, rPos, rArea, rTransform ); + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::draw + ////////////////////////////////////////////////////////////////////////////////// + + bool DXSurfaceBitmap::draw( double fAlpha, + const ::basegfx::B2DPoint& rPos, + const ::basegfx::B2DHomMatrix& rTransform ) + { + if( mbIsSurfaceDirty ) + { + mpSurfaceProxy->setColorBufferDirty(); + mbIsSurfaceDirty = false; + } + + return mpSurfaceProxy->draw( fAlpha, rPos, rTransform ); + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::draw + ////////////////////////////////////////////////////////////////////////////////// + + bool DXSurfaceBitmap::draw( const ::basegfx::B2IRange& rArea ) + { + if( mbIsSurfaceDirty ) + { + mpSurfaceProxy->setColorBufferDirty(); + mbIsSurfaceDirty = false; + } + + const double fAlpha(1.0); + const ::basegfx::B2DHomMatrix aTransform; + const ::basegfx::B2DRange aIEEEArea( rArea ); + return mpSurfaceProxy->draw(fAlpha, + ::basegfx::B2DPoint(), + aIEEEArea, + aTransform); + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::imageDebugger + ////////////////////////////////////////////////////////////////////////////////// +#if defined(DX_DEBUG_IMAGES) +# if OSL_DEBUG_LEVEL > 0 + void DXSurfaceBitmap::imageDebugger() + { +#if DIRECTX_VERSION < 0x0900 + DDSURFACEDESC aSurfaceDesc; + rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 ); + aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC); + + if( FAILED(mpSurface->Lock( NULL, + &aSurfaceDesc, + DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY, + NULL)) ) + return; + + imdebug("bgra w=%d h=%d %p", aSurfaceDesc.dwWidth, aSurfaceDesc.dwHeight, aSurfaceDesc.lpSurface); + + mpSurface->Unlock(NULL); +#else + D3DLOCKED_RECT aLockedRect; + if( FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)) ) + return; + + imdebug("bgra w=%d h=%d %p", maSize.getX(), + maSize.getY(), aLockedRect.pBits); + mpSurface->UnlockRect(); +#endif + } +# endif +#endif + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::getData + ////////////////////////////////////////////////////////////////////////////////// + + uno::Sequence< sal_Int8 > DXSurfaceBitmap::getData( rendering::IntegerBitmapLayout& /*bitmapLayout*/, + const geometry::IntegerRectangle2D& rect ) + { + if(hasAlpha()) + { + uno::Sequence< sal_Int8 > aRes( (rect.X2-rect.X1)*(rect.Y2-rect.Y1)*4 ); // TODO(F1): Be format-agnostic here + + const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) ); + + Gdiplus::BitmapData aBmpData; + aBmpData.Width = rect.X2-rect.X1; + aBmpData.Height = rect.Y2-rect.Y1; + aBmpData.Stride = 4*aBmpData.Width; + aBmpData.PixelFormat = PixelFormat32bppARGB; + aBmpData.Scan0 = aRes.getArray(); + + // TODO(F1): Support more pixel formats natively + + // read data from bitmap + if( Gdiplus::Ok != mpGDIPlusBitmap->LockBits( &aRect, + Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeUserInputBuf, + PixelFormat32bppARGB, // TODO(F1): Adapt to + // Graphics native + // format/change + // getMemoryLayout + &aBmpData ) ) + { + // failed to lock, bail out + return uno::Sequence< sal_Int8 >(); + } + + mpGDIPlusBitmap->UnlockBits( &aBmpData ); + + return aRes; + } + else + { + sal_uInt32 nWidth = rect.X2-rect.X1; + sal_uInt32 nHeight = rect.Y2-rect.Y1; + + uno::Sequence< sal_Int8 > aRes(nWidth*nHeight*4); + +#if DIRECTX_VERSION < 0x0900 + DDSURFACEDESC aSurfaceDesc; + rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0); + aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC); + const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY; + + // lock the directx surface to receive the pointer to the surface memory. + if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL))) + return uno::Sequence< sal_Int8 >(); + + sal_uInt8 *pSrc = (sal_uInt8 *)((((BYTE *)aSurfaceDesc.lpSurface)+(rect.Y1*aSurfaceDesc.lPitch))+rect.X1); + sal_uInt8 *pDst = (sal_uInt8 *)aRes.getArray(); + sal_uInt32 nSegmentSizeInBytes = nWidth<<4; + for(sal_uInt32 y=0; y<nHeight; ++y) + { + rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes); + pDst += nSegmentSizeInBytes; + pSrc += aSurfaceDesc.lPitch; + } + + mpSurface->Unlock(NULL); +#else + D3DLOCKED_RECT aLockedRect; + if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY))) + return uno::Sequence< sal_Int8 >(); + + sal_uInt8 *pSrc = (sal_uInt8 *)((((BYTE *)aLockedRect.pBits)+(rect.Y1*aLockedRect.Pitch))+rect.X1); + sal_uInt8 *pDst = (sal_uInt8 *)aRes.getArray(); + sal_uInt32 nSegmentSizeInBytes = nWidth<<4; + for(sal_uInt32 y=0; y<nHeight; ++y) + { + rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes); + pDst += nSegmentSizeInBytes; + pSrc += aLockedRect.Pitch; + } + + mpSurface->UnlockRect(); +#endif + return aRes; + } + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::setData + ////////////////////////////////////////////////////////////////////////////////// + + void DXSurfaceBitmap::setData( const uno::Sequence< sal_Int8 >& data, + const rendering::IntegerBitmapLayout& /*bitmapLayout*/, + const geometry::IntegerRectangle2D& rect ) + { + if(hasAlpha()) + { + const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) ); + + Gdiplus::BitmapData aBmpData; + aBmpData.Width = rect.X2-rect.X1; + aBmpData.Height = rect.Y2-rect.Y1; + aBmpData.Stride = 4*aBmpData.Width; + aBmpData.PixelFormat = PixelFormat32bppARGB; + aBmpData.Scan0 = (void*)data.getConstArray(); + + // TODO(F1): Support more pixel formats natively + + if( Gdiplus::Ok != mpGDIPlusBitmap->LockBits( &aRect, + Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf, + PixelFormat32bppARGB, // TODO: Adapt to + // Graphics native + // format/change + // getMemoryLayout + &aBmpData ) ) + { + throw uno::RuntimeException(); + } + + // commit data to bitmap + mpGDIPlusBitmap->UnlockBits( &aBmpData ); + } + else + { + sal_uInt32 nWidth = rect.X2-rect.X1; + sal_uInt32 nHeight = rect.Y2-rect.Y1; + +#if DIRECTX_VERSION < 0x0900 + DDSURFACEDESC aSurfaceDesc; + rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0); + aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC); + const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_WRITEONLY; + + // lock the directx surface to receive the pointer to the surface memory. + if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL))) + throw uno::RuntimeException(); + + sal_uInt8 *pSrc = (sal_uInt8 *)data.getConstArray(); + sal_uInt8 *pDst = (sal_uInt8 *)((((BYTE *)aSurfaceDesc.lpSurface)+(rect.Y1*aSurfaceDesc.lPitch))+rect.X1); + sal_uInt32 nSegmentSizeInBytes = nWidth<<4; + for(sal_uInt32 y=0; y<nHeight; ++y) + { + rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes); + pSrc += nSegmentSizeInBytes; + pDst += aSurfaceDesc.lPitch; + } + + mpSurface->Unlock(NULL); +#else + // lock the directx surface to receive the pointer to the surface memory. + D3DLOCKED_RECT aLockedRect; + if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY))) + throw uno::RuntimeException(); + + sal_uInt8 *pSrc = (sal_uInt8 *)data.getConstArray(); + sal_uInt8 *pDst = (sal_uInt8 *)((((BYTE *)aLockedRect.pBits)+(rect.Y1*aLockedRect.Pitch))+rect.X1); + sal_uInt32 nSegmentSizeInBytes = nWidth<<4; + for(sal_uInt32 y=0; y<nHeight; ++y) + { + rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes); + pSrc += nSegmentSizeInBytes; + pDst += aLockedRect.Pitch; + } + + mpSurface->UnlockRect(); +#endif + } + + mbIsSurfaceDirty = true; + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::setPixel + ////////////////////////////////////////////////////////////////////////////////// + + void DXSurfaceBitmap::setPixel( const uno::Sequence< sal_Int8 >& color, + const rendering::IntegerBitmapLayout& /*bitmapLayout*/, + const geometry::IntegerPoint2D& pos ) + { + if(hasAlpha()) + { + const geometry::IntegerSize2D aSize( maSize.getX(),maSize.getY() ); + + ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width, + "CanvasHelper::setPixel: X coordinate out of bounds" ); + ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height, + "CanvasHelper::setPixel: Y coordinate out of bounds" ); + ENSURE_ARG_OR_THROW( color.getLength() > 3, + "CanvasHelper::setPixel: not enough color components" ); + + if( Gdiplus::Ok != mpGDIPlusBitmap->SetPixel( pos.X, pos.Y, + Gdiplus::Color( tools::sequenceToArgb( color )))) + { + throw uno::RuntimeException(); + } + } + else + { + ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < maSize.getX(), + "CanvasHelper::setPixel: X coordinate out of bounds" ); + ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < maSize.getY(), + "CanvasHelper::setPixel: Y coordinate out of bounds" ); + ENSURE_ARG_OR_THROW( color.getLength() > 3, + "CanvasHelper::setPixel: not enough color components" ); + + Gdiplus::Color aColor(tools::sequenceToArgb(color)); + +#if DIRECTX_VERSION < 0x0900 + DDSURFACEDESC aSurfaceDesc; + rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0); + aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC); + const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_WRITEONLY; + + // lock the directx surface to receive the pointer to the surface memory. + if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL))) + throw uno::RuntimeException(); + + sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aSurfaceDesc.lpSurface)+(pos.Y*aSurfaceDesc.lPitch))+pos.X); + *pDst = aColor.GetValue(); + mpSurface->Unlock(NULL); +#else + // lock the directx surface to receive the pointer to the surface memory. + D3DLOCKED_RECT aLockedRect; + if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY))) + throw uno::RuntimeException(); + + sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aLockedRect.pBits)+(pos.Y*aLockedRect.Pitch))+pos.X); + *pDst = aColor.GetValue(); + mpSurface->UnlockRect(); +#endif + } + + mbIsSurfaceDirty = true; + } + + ////////////////////////////////////////////////////////////////////////////////// + // DXSurfaceBitmap::getPixel + ////////////////////////////////////////////////////////////////////////////////// + + uno::Sequence< sal_Int8 > DXSurfaceBitmap::getPixel( rendering::IntegerBitmapLayout& /*bitmapLayout*/, + const geometry::IntegerPoint2D& pos ) + { + if(hasAlpha()) + { + const geometry::IntegerSize2D aSize( maSize.getX(),maSize.getY() ); + + ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width, + "CanvasHelper::getPixel: X coordinate out of bounds" ); + ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height, + "CanvasHelper::getPixel: Y coordinate out of bounds" ); + + Gdiplus::Color aColor; + + if( Gdiplus::Ok != mpGDIPlusBitmap->GetPixel( pos.X, pos.Y, &aColor ) ) + return uno::Sequence< sal_Int8 >(); + + return tools::argbToIntSequence(aColor.GetValue()); + } + else + { + ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < maSize.getX(), + "CanvasHelper::getPixel: X coordinate out of bounds" ); + ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < maSize.getY(), + "CanvasHelper::getPixel: Y coordinate out of bounds" ); + +#if DIRECTX_VERSION < 0x0900 + DDSURFACEDESC aSurfaceDesc; + rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0); + aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC); + const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY; + + // lock the directx surface to receive the pointer to the surface memory. + if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL))) + throw uno::RuntimeException(); + + sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aSurfaceDesc.lpSurface)+(pos.Y*aSurfaceDesc.lPitch))+pos.X); + Gdiplus::Color aColor(*pDst); + mpSurface->Unlock(NULL); +#else + // lock the directx surface to receive the pointer to the surface memory. + D3DLOCKED_RECT aLockedRect; + if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY))) + throw uno::RuntimeException(); + + sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aLockedRect.pBits)+(pos.Y*aLockedRect.Pitch))+pos.X); + Gdiplus::Color aColor(*pDst); + mpSurface->UnlockRect(); +#endif + + return tools::argbToIntSequence(aColor.GetValue()); + } + } + + ////////////////////////////////////////////////////////////////////////////////// + // End of file + ////////////////////////////////////////////////////////////////////////////////// +} + |