1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include <ctype.h> // don't ask. msdev breaks otherwise...
29 #include <vcl/window.hxx>
30 #include <canvas/debug.hxx>
31 #include <canvas/verbosetrace.hxx>
32 #include <canvas/canvastools.hxx>
33 #include <tools/diagnose_ex.h>
34 
35 #include <osl/mutex.hxx>
36 #include <cppuhelper/compbase1.hxx>
37 
38 #include <com/sun/star/lang/NoSupportException.hpp>
39 #include <toolkit/helper/vclunohelper.hxx>
40 #include <basegfx/tools/canvastools.hxx>
41 #include "dx_linepolypolygon.hxx"
42 #include "dx_spritecanvas.hxx"
43 #include "dx_canvasbitmap.hxx"
44 #include "dx_spritedevicehelper.hxx"
45 
46 
47 #undef WB_LEFT
48 #undef WB_RIGHT
49 #include "dx_winstuff.hxx"
50 
51 
52 #include <vcl/sysdata.hxx>
53 
54 using namespace ::com::sun::star;
55 
56 namespace dxcanvas
57 {
58     SpriteDeviceHelper::SpriteDeviceHelper() :
59         DeviceHelper(),
60         mpSpriteCanvas( NULL ),
61         mpSurfaceProxyManager(),
62         mpRenderModule(),
63         mpBackBuffer()
64     {
65     }
66 
67     void SpriteDeviceHelper::init( Window&               rWindow,
68                                    SpriteCanvas&		 rSpriteCanvas,
69                                    const awt::Rectangle& rRect,
70                                    bool                  /*bFullscreen*/ )
71     {
72         // #i60490# ensure backbuffer has sensible minimal size
73 		const sal_Int32 w( ::std::max(sal_Int32(1),sal_Int32(rRect.Width)));
74         const sal_Int32 h( ::std::max(sal_Int32(1),sal_Int32(rRect.Height)));
75 
76         rSpriteCanvas.setWindow(
77             uno::Reference<awt::XWindow2>(
78                 VCLUnoHelper::GetInterface(&rWindow),
79                 uno::UNO_QUERY_THROW) );
80 
81 		const SystemEnvData *pData = rWindow.GetSystemData();
82 		const HWND hWnd = reinterpret_cast<HWND>(pData->hWnd);
83         if( !IsWindow( hWnd ) )
84             throw lang::NoSupportException(
85                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
86                                      "Passed window has invalid system window, or canvas out-of-process!")),
87                 NULL);
88 
89         mpSpriteCanvas = &rSpriteCanvas;
90 
91 		try
92 		{
93 			// setup directx rendermodule
94 			mpRenderModule = createRenderModule( rWindow );
95 		}
96 		catch (...) {
97 
98 			throw lang::NoSupportException(
99                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
100                                      "Could not create DirectX device!") ),
101                 static_cast< ::cppu::OWeakObject* >(&rSpriteCanvas) );
102 		}
103 
104 		// create the surfaceproxy manager
105         mpSurfaceProxyManager = ::canvas::createSurfaceProxyManager( mpRenderModule );
106 
107         // #i60490# ensure backbuffer has sensible minimal size
108 		mpBackBuffer.reset(new DXSurfaceBitmap(
109                                ::basegfx::B2ISize(w,h),
110                                mpSurfaceProxyManager,
111                                mpRenderModule,
112                                false));
113 
114         // Assumes: SystemChildWindow() has CS_OWNDC
115         DeviceHelper::init(GetDC(mpRenderModule->getHWND()),
116                            rSpriteCanvas);
117     }
118 
119     void SpriteDeviceHelper::disposing()
120     {
121         // release all references
122         mpBackBuffer.reset();
123 		mpSurfaceProxyManager.reset();
124         mpRenderModule.reset();
125         mpSpriteCanvas = NULL;
126 
127         DeviceHelper::disposing();
128     }
129 
130     uno::Reference< rendering::XBitmap > SpriteDeviceHelper::createCompatibleBitmap(
131         const uno::Reference< rendering::XGraphicDevice >& 	/*rDevice*/,
132         const geometry::IntegerSize2D& 						size )
133     {
134         if( !getDevice() )
135             return uno::Reference< rendering::XBitmap >(); // we're disposed
136 
137 		DXSurfaceBitmapSharedPtr pBitmap(
138 			new DXSurfaceBitmap(
139 				::basegfx::unotools::b2ISizeFromIntegerSize2D(size),
140 				mpSurfaceProxyManager,
141 				mpRenderModule,
142 				false));
143 
144 		// create a 24bit RGB system memory surface
145         return uno::Reference< rendering::XBitmap >(new CanvasBitmap(pBitmap,getDevice()));
146     }
147 
148     uno::Reference< rendering::XVolatileBitmap > SpriteDeviceHelper::createVolatileBitmap(
149         const uno::Reference< rendering::XGraphicDevice >& 	/*rDevice*/,
150         const geometry::IntegerSize2D& 						/*size*/ )
151     {
152         return uno::Reference< rendering::XVolatileBitmap >();
153     }
154 
155     uno::Reference< rendering::XBitmap > SpriteDeviceHelper::createCompatibleAlphaBitmap(
156         const uno::Reference< rendering::XGraphicDevice >& 	/*rDevice*/,
157         const geometry::IntegerSize2D& 						size )
158     {
159         if( !getDevice() )
160             return uno::Reference< rendering::XBitmap >(); // we're disposed
161 
162 		DXSurfaceBitmapSharedPtr pBitmap(
163 			new DXSurfaceBitmap(
164 				::basegfx::unotools::b2ISizeFromIntegerSize2D(size),
165 				mpSurfaceProxyManager,
166 				mpRenderModule,
167 				true));
168 
169 		// create a 32bit ARGB system memory surface
170         return uno::Reference< rendering::XBitmap >(new CanvasBitmap(pBitmap,getDevice()));
171     }
172 
173     uno::Reference< rendering::XVolatileBitmap > SpriteDeviceHelper::createVolatileAlphaBitmap(
174         const uno::Reference< rendering::XGraphicDevice >& 	/*rDevice*/,
175         const geometry::IntegerSize2D& 						/*size*/ )
176     {
177         return uno::Reference< rendering::XVolatileBitmap >();
178     }
179 
180     sal_Bool SpriteDeviceHelper::hasFullScreenMode()
181     {
182         // TODO(F3): offer fullscreen mode the XCanvas way
183         return false;
184     }
185 
186     sal_Bool SpriteDeviceHelper::enterFullScreenMode( sal_Bool /*bEnter*/ )
187     {
188         // TODO(F3): offer fullscreen mode the XCanvas way
189         return false;
190     }
191 
192     ::sal_Int32 SpriteDeviceHelper::createBuffers( ::sal_Int32 /*nBuffers*/ )
193     {
194         // TODO(F3): implement XBufferStrategy interface. For now, we
195         // _always_ will have exactly one backbuffer
196         return 1;
197     }
198 
199     void SpriteDeviceHelper::destroyBuffers()
200     {
201         // TODO(F3): implement XBufferStrategy interface. For now, we
202         // _always_ will have exactly one backbuffer
203     }
204 
205     ::sal_Bool SpriteDeviceHelper::showBuffer( bool, ::sal_Bool )
206     {
207         OSL_ENSURE(false,"Not supposed to be called, handled by SpriteCanvas");
208         return sal_False;
209     }
210 
211     ::sal_Bool SpriteDeviceHelper::switchBuffer( bool, ::sal_Bool )
212     {
213         OSL_ENSURE(false,"Not supposed to be called, handled by SpriteCanvas");
214         return sal_False;
215     }
216 
217     uno::Any SpriteDeviceHelper::isAccelerated() const
218     {
219         return ::com::sun::star::uno::makeAny(true);
220     }
221 
222     void SpriteDeviceHelper::notifySizeUpdate( const awt::Rectangle& rBounds )
223     {
224         // #i60490# ensure backbuffer has sensible minimal size
225 		const sal_Int32 x(rBounds.X);
226 		const sal_Int32 y(rBounds.Y);
227 		const sal_Int32 w(::std::max(sal_Int32(1),sal_Int32(rBounds.Width)));
228         const sal_Int32 h(::std::max(sal_Int32(1),sal_Int32(rBounds.Height)));
229 
230         if( mpRenderModule )
231             mpRenderModule->resize(::basegfx::B2IRange(x,y,x+w,y+h));
232 
233         resizeBackBuffer(::basegfx::B2ISize(w,h));
234     }
235 
236     void SpriteDeviceHelper::resizeBackBuffer( const ::basegfx::B2ISize& rNewSize )
237     {
238         // disposed?
239         if(!(mpBackBuffer))
240             return;
241 
242 		mpBackBuffer->resize(rNewSize);
243 		mpBackBuffer->clear();
244     }
245 
246     HWND SpriteDeviceHelper::getHwnd() const
247     {
248         if( mpRenderModule )
249             return mpRenderModule->getHWND();
250         else
251             return 0;
252     }
253 
254     void SpriteDeviceHelper::dumpScreenContent() const
255     {
256         if( mpRenderModule )
257             mpRenderModule->screenShot();
258     }
259 }
260