update dev300-m58
[ooovba.git] / canvas / source / directx / dx_spritecanvashelper.cxx
blobeca38eeb7eb91875d3b08fdf897a011dd1be15a0
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dx_spritecanvashelper.cxx,v $
10 * $Revision: 1.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_canvas.hxx"
34 #include <canvas/debug.hxx>
35 #include <canvas/verbosetrace.hxx>
36 #include <canvas/canvastools.hxx>
37 #include <tools/diagnose_ex.h>
39 #include <comphelper/scopeguard.hxx>
41 #include <basegfx/range/b2drectangle.hxx>
42 #include <basegfx/tools/canvastools.hxx>
44 #include <boost/cast.hpp>
46 #include "dx_spritecanvashelper.hxx"
47 #include "dx_canvascustomsprite.hxx"
49 #if defined(DX_DEBUG_IMAGES)
50 # if OSL_DEBUG_LEVEL > 0
51 # include <imdebug.h>
52 # undef min
53 # undef max
54 # endif
55 #endif
57 using namespace ::com::sun::star;
59 namespace dxcanvas
61 namespace
63 void repaintBackground( const ::basegfx::B2DRange& rUpdateArea,
64 const ::basegfx::B2IRange& rOutputArea,
65 const DXSurfaceBitmapSharedPtr& rBackBuffer )
67 // TODO(E1): Use numeric_cast to catch overflow here
68 ::basegfx::B2IRange aActualArea( 0, 0,
69 static_cast<sal_Int32>(rOutputArea.getWidth()),
70 static_cast<sal_Int32>(rOutputArea.getHeight()) );
71 aActualArea.intersect( fround( rUpdateArea ) );
73 // repaint the given area of the screen with background content
74 rBackBuffer->draw(aActualArea);
77 void spriteRedraw( const ::canvas::Sprite::Reference& rSprite )
79 // downcast to derived dxcanvas::Sprite interface, which
80 // provides the actual redraw methods.
81 ::boost::polymorphic_downcast< Sprite* >(
82 rSprite.get() )->redraw();
85 void spriteRedrawStub( const ::canvas::Sprite::Reference& rSprite )
87 if( rSprite.is() )
89 // downcast to derived dxcanvas::Sprite interface, which
90 // provides the actual redraw methods.
91 ::boost::polymorphic_downcast< Sprite* >(
92 rSprite.get() )->redraw();
96 void spriteRedrawStub2( const ::canvas::SpriteRedrawManager::AreaComponent& rComponent )
98 if( rComponent.second.getSprite().is() )
100 // downcast to derived dxcanvas::Sprite interface, which
101 // provides the actual redraw methods.
102 ::boost::polymorphic_downcast< Sprite* >(
103 rComponent.second.getSprite().get() )->redraw();
108 SpriteCanvasHelper::SpriteCanvasHelper() :
109 mpSpriteSurface( NULL ),
110 mpRedrawManager( NULL ),
111 mpRenderModule(),
112 mpSurfaceProxy(),
113 mpBackBuffer(),
114 maUpdateRect(),
115 maScrapRect(),
116 mbShowSpriteBounds( false )
118 #if defined(VERBOSE) && defined(DBG_UTIL)
119 // inverse default for verbose debug mode
120 mbShowSpriteBounds = true;
121 #endif
124 void SpriteCanvasHelper::init( SpriteCanvas& rParent,
125 ::canvas::SpriteRedrawManager& rManager,
126 const IDXRenderModuleSharedPtr& rRenderModule,
127 const ::canvas::ISurfaceProxyManagerSharedPtr& rSurfaceProxy,
128 const DXSurfaceBitmapSharedPtr& rBackBuffer,
129 const ::basegfx::B2ISize& rOutputOffset )
131 // init base
132 setDevice( rParent );
133 setTarget( rBackBuffer, rOutputOffset );
135 mpSpriteSurface = &rParent;
136 mpRedrawManager = &rManager;
137 mpRenderModule = rRenderModule;
138 mpSurfaceProxy = rSurfaceProxy;
139 mpBackBuffer = rBackBuffer;
142 void SpriteCanvasHelper::disposing()
144 if(mpRenderModule)
145 mpRenderModule->disposing();
147 mpBackBuffer.reset();
148 mpRenderModule.reset();
149 mpRedrawManager = NULL;
150 mpSpriteSurface = NULL;
152 // forward to base
153 CanvasHelper::disposing();
156 uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromAnimation(
157 const uno::Reference< rendering::XAnimation >& /*animation*/ )
159 return uno::Reference< rendering::XAnimatedSprite >();
162 uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromBitmaps(
163 const uno::Sequence< uno::Reference< rendering::XBitmap > >& /*animationBitmaps*/,
164 sal_Int8 /*interpolationMode*/ )
166 return uno::Reference< rendering::XAnimatedSprite >();
169 uno::Reference< rendering::XCustomSprite > SpriteCanvasHelper::createCustomSprite( const geometry::RealSize2D& spriteSize )
171 if( !mpRedrawManager )
172 return uno::Reference< rendering::XCustomSprite >(); // we're disposed
174 return uno::Reference< rendering::XCustomSprite >(
175 new CanvasCustomSprite( spriteSize,
176 mpSpriteSurface,
177 mpRenderModule,
178 mpSurfaceProxy,
179 mbShowSpriteBounds ) );
182 uno::Reference< rendering::XSprite > SpriteCanvasHelper::createClonedSprite( const uno::Reference< rendering::XSprite >& /*original*/ )
184 return uno::Reference< rendering::XSprite >();
187 sal_Bool SpriteCanvasHelper::updateScreen( const ::basegfx::B2IRectangle& rCurrArea,
188 sal_Bool bUpdateAll,
189 bool& io_bSurfaceDirty )
191 if( !mpRedrawManager ||
192 !mpRenderModule ||
193 !mpBackBuffer )
195 return sal_False; // disposed, or otherwise dysfunctional
198 #if defined(DX_DEBUG_IMAGES)
199 # if OSL_DEBUG_LEVEL > 0
200 mpBackBuffer->imageDebugger();
201 # endif
202 #endif
204 // store current output area (need to tunnel that to the
205 // background, scroll, opaque and general sprite repaint
206 // routines)
207 maScrapRect = rCurrArea;
209 // clear area that needs to be blitted to screen beforehand
210 maUpdateRect.reset();
212 // TODO(P1): Might be worthwile to track areas of background
213 // changes, too.
215 // TODO(P2): Might be worthwhile to use page-flipping only if
216 // a certain percentage of screen area has changed - and
217 // compose directly to the front buffer otherwise.
218 if( !bUpdateAll && !io_bSurfaceDirty )
220 // background has not changed, so we're free to optimize
221 // repaint to areas where a sprite has changed
223 // process each independent area of overlapping sprites
224 // separately.
225 mpRedrawManager->forEachSpriteArea( *this );
227 // flip primary surface to screen
228 // ==============================
230 // perform buffer flipping
231 mpRenderModule->flip( maUpdateRect,
232 rCurrArea );
234 else
236 // limit update to parent window area (ignored for fullscreen)
237 // TODO(E1): Use numeric_cast to catch overflow here
238 const ::basegfx::B2IRectangle aUpdateArea( 0,0,
239 static_cast<sal_Int32>(rCurrArea.getWidth()),
240 static_cast<sal_Int32>(rCurrArea.getHeight()) );
242 // background has changed, or called requested full
243 // update, or we're performing double buffering via page
244 // flipping, so we currently have no choice but repaint
245 // everything
247 // repaint the whole screen with background content
248 mpBackBuffer->draw(aUpdateArea);
250 // redraw sprites
251 mpRedrawManager->forEachSprite(::std::ptr_fun( &spriteRedraw ) );
253 // flip primary surface to screen
254 // ==============================
256 // perform buffer flipping
257 mpRenderModule->flip( aUpdateArea,
258 rCurrArea );
261 // change record vector must be cleared, for the next turn of
262 // rendering and sprite changing
263 mpRedrawManager->clearChangeRecords();
265 io_bSurfaceDirty = false;
267 return sal_True;
270 void SpriteCanvasHelper::backgroundPaint( const ::basegfx::B2DRange& rUpdateRect )
272 ENSURE_OR_THROW( mpRenderModule &&
273 mpBackBuffer,
274 "SpriteCanvasHelper::backgroundPaint(): NULL device pointer " );
276 repaintBackground( rUpdateRect,
277 maScrapRect,
278 mpBackBuffer );
281 void SpriteCanvasHelper::scrollUpdate( const ::basegfx::B2DRange& /*rMoveStart*/,
282 const ::basegfx::B2DRange& rMoveEnd,
283 const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea )
285 ENSURE_OR_THROW( mpRenderModule &&
286 mpBackBuffer,
287 "SpriteCanvasHelper::scrollUpdate(): NULL device pointer " );
289 // round rectangles to integer pixel. Note: have to be
290 // extremely careful here, to avoid off-by-one errors for
291 // the destination area: otherwise, the next scroll update
292 // would copy pixel that are not supposed to be part of
293 // the sprite.
294 const ::basegfx::B2IRange& rDestRect(
295 ::canvas::tools::spritePixelAreaFromB2DRange( rMoveEnd ) );
297 // not much sense in really implementing scrollUpdate here,
298 // since outputting a sprite only partially would result in
299 // expensive clipping. Furthermore, we cannot currently render
300 // 3D directly to the front buffer, thus, would have to blit
301 // the full sprite area, anyway. But at least optimized in the
302 // sense that unnecessary background paints behind the sprites
303 // are avoided.
304 ::std::for_each( rUpdateArea.maComponentList.begin(),
305 rUpdateArea.maComponentList.end(),
306 ::std::ptr_fun( &spriteRedrawStub2 ) );
308 // repaint uncovered areas from backbuffer - take the
309 // _rounded_ rectangles from above, to have the update
310 // consistent with the scroll above.
311 ::std::vector< ::basegfx::B2DRange > aUncoveredAreas;
312 ::basegfx::computeSetDifference( aUncoveredAreas,
313 rUpdateArea.maTotalBounds,
314 ::basegfx::B2DRange( rDestRect ) );
315 ::std::for_each( aUncoveredAreas.begin(),
316 aUncoveredAreas.end(),
317 ::boost::bind( &repaintBackground,
319 ::boost::cref(maScrapRect),
320 ::boost::cref(mpBackBuffer) ) );
322 // TODO(E1): Use numeric_cast to catch overflow here
323 ::basegfx::B2IRange aActualArea( 0, 0,
324 static_cast<sal_Int32>(maScrapRect.getWidth()),
325 static_cast<sal_Int32>(maScrapRect.getHeight()) );
326 aActualArea.intersect( fround( rUpdateArea.maTotalBounds ) );
328 // add given update area to the 'blit to foreground' rect
329 maUpdateRect.expand( aActualArea );
332 void SpriteCanvasHelper::opaqueUpdate( const ::basegfx::B2DRange& rTotalArea,
333 const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
335 ENSURE_OR_THROW( mpRenderModule &&
336 mpBackBuffer,
337 "SpriteCanvasHelper::opaqueUpdate(): NULL device pointer " );
339 // TODO(P2): optimize this by truly rendering to the front
340 // buffer. Currently, we've the 3D device only for the back
341 // buffer.
342 ::std::for_each( rSortedUpdateSprites.begin(),
343 rSortedUpdateSprites.end(),
344 ::std::ptr_fun( &spriteRedrawStub ) );
346 // TODO(E1): Use numeric_cast to catch overflow here
347 ::basegfx::B2IRange aActualArea( 0, 0,
348 static_cast<sal_Int32>(maScrapRect.getWidth()),
349 static_cast<sal_Int32>(maScrapRect.getHeight()) );
350 aActualArea.intersect( fround( rTotalArea ) );
352 // add given update area to the 'blit to foreground' rect
353 maUpdateRect.expand( aActualArea );
356 void SpriteCanvasHelper::genericUpdate( const ::basegfx::B2DRange& rTotalArea,
357 const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
359 ENSURE_OR_THROW( mpRenderModule &&
360 mpBackBuffer,
361 "SpriteCanvasHelper::genericUpdate(): NULL device pointer " );
363 // paint background
364 // ================
366 // TODO(E1): Use numeric_cast to catch overflow here
367 ::basegfx::B2IRange aActualArea( 0, 0,
368 static_cast<sal_Int32>(maScrapRect.getWidth()),
369 static_cast<sal_Int32>(maScrapRect.getHeight()) );
370 aActualArea.intersect( fround( rTotalArea ) );
372 // repaint the given area of the screen with background content
373 mpBackBuffer->draw(aActualArea);
375 // paint sprite
376 // ============
378 ::std::for_each( rSortedUpdateSprites.begin(),
379 rSortedUpdateSprites.end(),
380 ::std::ptr_fun( &spriteRedrawStub ) );
382 // add given update area to the 'blit to foreground' rect
383 maUpdateRect.expand( aActualArea );