ooo-build r15307 - in trunk: . patches/test



Author: thorstenb
Date: Mon Feb  9 23:15:45 2009
New Revision: 15307
URL: http://svn.gnome.org/viewvc/ooo-build?rev=15307&view=rev

Log:
    * patches/test/opengl-canvas.diff: added slideshow fixes to ensure
    'clear'-ed background for each new slide; added seven-segment
    display polygon synthesis to basegfx (for onscreen debug output);
    added informational debug output to oglcanvas; added pbuffer
    support (need that for global alpha & clipping, especially for
    sprites)



Modified:
   trunk/ChangeLog
   trunk/patches/test/opengl-canvas.diff

Modified: trunk/patches/test/opengl-canvas.diff
==============================================================================
--- trunk/patches/test/opengl-canvas.diff	(original)
+++ trunk/patches/test/opengl-canvas.diff	Mon Feb  9 23:15:45 2009
@@ -1,3 +1,75 @@
+Necessary slideshow changes for working properly with ogl canvas
+
+From: Thorsten Behrens <thb openoffice org>
+
+
+---
+
+ slideshow/source/engine/slideview.cxx              |    9 +++++----
+ .../source/engine/transitions/slidechangebase.cxx  |    1 +
+ .../engine/transitions/slidetransitionfactory.cxx  |    2 ++
+ 3 files changed, 8 insertions(+), 4 deletions(-)
+
+
+diff --git slideshow/source/engine/slideview.cxx slideshow/source/engine/slideview.cxx
+index ad511f5..6a11cda 100644
+--- slideshow/source/engine/slideview.cxx
++++ slideshow/source/engine/slideview.cxx
+@@ -888,6 +888,11 @@ void SlideView::clearAll() const
+     if( !mxView.is() || !mpCanvas )
+         return;
+ 
++    mpCanvas->clear(); // this is unnecessary, strictly speaking. but
++                       // it makes the SlideView behave exactly like a
++                       // sprite-based SlideViewLayer, because those
++                       // are created from scratch after a resize
++
+     // clear whole view
+     mxView->clear();
+ }
+@@ -1091,10 +1096,6 @@ void SlideView::updateCanvas()
+     if( !mpCanvas || !mxView.is())
+         return;
+     
+-    mpCanvas->clear(); // this is unnecessary, strictly speaking. but
+-                       // it makes the SlideView behave exactly like a
+-                       // sprite-based SlideViewLayer, because those
+-                       // are created from scratch after a resize
+     clearAll();
+     mpCanvas->setTransformation( getTransformation() );
+     mpCanvas->setClip( 
+diff --git slideshow/source/engine/transitions/slidechangebase.cxx slideshow/source/engine/transitions/slidechangebase.cxx
+index 2983e6b..1432b95 100644
+--- slideshow/source/engine/transitions/slidechangebase.cxx
++++ slideshow/source/engine/transitions/slidechangebase.cxx
+@@ -245,6 +245,7 @@ void SlideChangeBase::end()
+ 
+             const SlideBitmapSharedPtr pSlideBitmap( getEnteringBitmap( *aCurr ));
+             pSlideBitmap->clip( basegfx::B2DPolyPolygon() /* no clipping */ );
++            aCurr->mpView->clearAll();
+             renderBitmap( pSlideBitmap,
+                           aCurr->mpView->getCanvas() );
+ 
+diff --git slideshow/source/engine/transitions/slidetransitionfactory.cxx slideshow/source/engine/transitions/slidetransitionfactory.cxx
+index b82025a..f3a22e9 100644
+--- slideshow/source/engine/transitions/slidetransitionfactory.cxx
++++ slideshow/source/engine/transitions/slidetransitionfactory.cxx
+@@ -421,6 +421,7 @@ void MovingSlideChange::performIn(
+     if (mbFirstPerformCall && maLeavingDirection.equalZero()) 
+     {
+         mbFirstPerformCall = false;
++        rViewEntry.mpView->clearAll();
+         renderBitmap( getLeavingBitmap(rViewEntry), rDestinationCanvas );
+     }
+     
+@@ -459,6 +460,7 @@ void MovingSlideChange::performOut(
+     if (mbFirstPerformCall && maEnteringDirection.equalZero()) 
+     {
+         mbFirstPerformCall = false;
++        rViewEntry.mpView->clearAll();
+         renderBitmap( getEnteringBitmap(rViewEntry), rDestinationCanvas );
+     }
+     
 A hackweek project - doing XCanvas API natively in OpenGL
 
 From: Thorsten Behrens <thb openoffice org>
@@ -5,6 +77,11 @@
 
 ---
 
+ .../inc/basegfx/polygon/b2dpolypolygontools.hxx    |   20 
+ basegfx/inc/basegfx/tools/tools.hxx                |   25 
+ basegfx/source/polygon/b2dpolypolygontools.cxx     |  132 +++
+ basegfx/source/tools/makefile.mk                   |    1 
+ basegfx/source/tools/numbertools.cxx               |   79 ++
  canvas/prj/build.lst                               |    1 
  canvas/prj/d.lst                                   |    2 
  canvas/source/cairo/cairo_canvashelper.hxx         |    1 
@@ -12,25 +89,28 @@
  canvas/source/null/null_canvashelper.hxx           |    1 
  canvas/source/opengl/exports.dxp                   |    3 
  canvas/source/opengl/exports.map                   |    8 
- canvas/source/opengl/makefile.mk                   |   66 +
+ canvas/source/opengl/makefile.mk                   |   67 +
  canvas/source/opengl/ogl_bitmapcanvashelper.cxx    |  108 ++
  canvas/source/opengl/ogl_bitmapcanvashelper.hxx    |  107 ++
+ canvas/source/opengl/ogl_buffercontext.hxx         |   38 +
  canvas/source/opengl/ogl_canvasbitmap.cxx          |   63 +
  canvas/source/opengl/ogl_canvasbitmap.hxx          |   82 ++
- canvas/source/opengl/ogl_canvascustomsprite.cxx    |  154 +++
- canvas/source/opengl/ogl_canvascustomsprite.hxx    |  101 ++
+ canvas/source/opengl/ogl_canvascustomsprite.cxx    |  226 ++++
+ canvas/source/opengl/ogl_canvascustomsprite.hxx    |  103 ++
  canvas/source/opengl/ogl_canvasfont.cxx            |   88 ++
  canvas/source/opengl/ogl_canvasfont.hxx            |   72 +
- canvas/source/opengl/ogl_canvashelper.cxx          | 1092 ++++++++++++++++++++
- canvas/source/opengl/ogl_canvashelper.hxx          |  238 ++++
+ canvas/source/opengl/ogl_canvashelper.cxx          | 1019 ++++++++++++++++++++
+ canvas/source/opengl/ogl_canvashelper.hxx          |  242 +++++
+ canvas/source/opengl/ogl_canvastools.cxx           |  147 +++
+ canvas/source/opengl/ogl_canvastools.hxx           |   41 +
  canvas/source/opengl/ogl_spritecanvas.cxx          |  202 ++++
  canvas/source/opengl/ogl_spritecanvas.hxx          |  126 ++
- canvas/source/opengl/ogl_spritedevicehelper.cxx    |  774 ++++++++++++++
- canvas/source/opengl/ogl_spritedevicehelper.hxx    |  152 +++
+ canvas/source/opengl/ogl_spritedevicehelper.cxx    |  991 +++++++++++++++++++
+ canvas/source/opengl/ogl_spritedevicehelper.hxx    |  176 +++
  canvas/source/opengl/ogl_textlayout.cxx            |  222 ++++
  canvas/source/opengl/ogl_textlayout.hxx            |   83 ++
- canvas/source/opengl/ogl_texturecache.cxx          |   95 ++
- canvas/source/opengl/ogl_texturecache.hxx          |   45 +
+ canvas/source/opengl/ogl_texturecache.cxx          |  132 +++
+ canvas/source/opengl/ogl_texturecache.hxx          |   68 +
  canvas/source/opengl/ogl_tools.hxx                 |   35 +
  canvas/source/tools/canvastools.cxx                |   10 
  canvas/source/vcl/canvashelper.hxx                 |    1 
@@ -47,17 +127,20 @@
  sd/source/ui/presenter/PresenterCanvas.hxx         |    4 
  sd/source/ui/presenter/PresenterTextView.cxx       |    1 
  sd/source/ui/presenter/SlideRenderer.cxx           |    1 
+ sd/source/ui/slideshow/slideshowimpl.cxx           |    7 
  sd/source/ui/slideshow/slideshowviewimpl.cxx       |   13 
  sd/source/ui/slideshow/slideshowviewimpl.hxx       |    1 
  sdext/source/presenter/PresenterSlideShowView.cxx  |   48 +
  sdext/source/presenter/PresenterSlideShowView.hxx  |    7 
  slideshow/source/engine/waitsymbol.cxx             |   13 
- 47 files changed, 4037 insertions(+), 64 deletions(-)
+ 56 files changed, 4833 insertions(+), 65 deletions(-)
+ create mode 100644 basegfx/source/tools/numbertools.cxx
  create mode 100644 canvas/source/opengl/exports.dxp
  create mode 100644 canvas/source/opengl/exports.map
  create mode 100644 canvas/source/opengl/makefile.mk
  create mode 100644 canvas/source/opengl/ogl_bitmapcanvashelper.cxx
  create mode 100644 canvas/source/opengl/ogl_bitmapcanvashelper.hxx
+ create mode 100644 canvas/source/opengl/ogl_buffercontext.hxx
  create mode 100644 canvas/source/opengl/ogl_canvasbitmap.cxx
  create mode 100644 canvas/source/opengl/ogl_canvasbitmap.hxx
  create mode 100644 canvas/source/opengl/ogl_canvascustomsprite.cxx
@@ -66,6 +149,8 @@
  create mode 100644 canvas/source/opengl/ogl_canvasfont.hxx
  create mode 100644 canvas/source/opengl/ogl_canvashelper.cxx
  create mode 100644 canvas/source/opengl/ogl_canvashelper.hxx
+ create mode 100644 canvas/source/opengl/ogl_canvastools.cxx
+ create mode 100644 canvas/source/opengl/ogl_canvastools.hxx
  create mode 100644 canvas/source/opengl/ogl_spritecanvas.cxx
  create mode 100644 canvas/source/opengl/ogl_spritecanvas.hxx
  create mode 100644 canvas/source/opengl/ogl_spritedevicehelper.cxx
@@ -78,6 +163,320 @@
  create mode 100644 scp2/source/canvas/openglcanvas.scp
 
 
+diff --git basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx
+index dd56633..d25558c 100644
+--- basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx
++++ basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx
+@@ -257,6 +257,26 @@ namespace basegfx
+         */
+ 		B2DPolyPolygon reSegmentPolyPolygonEdges(const B2DPolyPolygon& rCandidate, sal_uInt32 nSubEdges, bool bHandleCurvedEdges, bool bHandleStraightEdges);
+ 
++        /** Creates polypolygon for seven-segment display number
++
++            This function takes an integer number between 0 and 9 and
++            convert it into the well-known seven-segment display
++            number (like most digital clocks show their numbers). The
++            digit will exactly fit the unit rectangle. The polypolygon
++            will be a line polygon, i.e. if you need the segment parts
++            to have width, use createAreaGeometry() on the result.
++
++            @param cNumber
++            Number from '0' to '9' as ASCII char, or '-', 'E' and '.' 
++            to convert to 7 segment code
++
++            @param bLitSegments
++            When true, return a polygon containing the segments that
++            are 'lit' for the given number. Return un-lit segments
++            otherwise.
++         */
++		B2DPolyPolygon createSevenSegmentPolyPolygon(sal_Char cNumber, bool bLitSegments=true);
++
+ 		//////////////////////////////////////////////////////////////////////
+ 		// comparators with tolerance for 2D PolyPolygons
+ 		bool equal(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB, const double& rfSmallValue);
+diff --git basegfx/inc/basegfx/tools/tools.hxx basegfx/inc/basegfx/tools/tools.hxx
+index 62ad8de..cc89fb4 100644
+--- basegfx/inc/basegfx/tools/tools.hxx
++++ basegfx/inc/basegfx/tools/tools.hxx
+@@ -37,6 +37,7 @@ namespace basegfx
+ {
+     class B2DPoint;
+     class B2DRange;
++    class B2DPolyPolygon;
+ 
+     namespace tools
+     {
+@@ -128,6 +129,30 @@ namespace basegfx
+                                             ::basegfx::B2DPoint& 		io_rRightBottom,
+                                             const ::basegfx::B2DRange&	rFitTarget	);
+ 
++        /** Creates polypolygon with the given number as seven-segment
++            digits
++
++            @param fVal
++            Value to convert
++
++            @param nTotalDigits
++            Total number of digits to display. If less is needed for
++            given number, fill space with blanks.
++
++            @param nDecPlaces 
++            Decimal places to show. When 0, display as integer. When
++            negative, fill given number of before-the-decimal point
++            with zero.
++
++            @param bLitSegments
++            When true, return a polygon containing the segments that
++            are 'lit' for the given number. Return un-lit segments
++            otherwise.
++         */
++		B2DPolyPolygon number2PolyPolygon(double    fVal, 
++                                          sal_Int32 nTotalDigits, 
++                                          sal_Int32 nDecPlaces, 
++                                          bool      bLitSegments=true);
+     }
+ }
+ 
+diff --git basegfx/source/polygon/b2dpolypolygontools.cxx basegfx/source/polygon/b2dpolypolygontools.cxx
+index 485287f..06093c9 100644
+--- basegfx/source/polygon/b2dpolypolygontools.cxx
++++ basegfx/source/polygon/b2dpolypolygontools.cxx
+@@ -569,6 +569,138 @@ namespace basegfx
+ 			return equal(rCandidateA, rCandidateB, fSmallValue);
+ 		}
+ 
++		B2DPolyPolygon createSevenSegmentPolyPolygon(sal_Char nNumber, bool bLitSegments)
++        {
++            // config here
++            // {
++            const double fTotalSize=1.0;
++            const double fPosMiddleSegment=0.6;
++            const double fSegmentEndChopHoriz=0.08;
++            const double fSegmentEndChopVert =0.04;
++            // }
++            // config here
++
++            const double fLeft=0.0;
++            const double fRight=fTotalSize;
++            const double fTop=0.0;
++            const double fMiddle=fPosMiddleSegment;
++            const double fBottom=fTotalSize;
++
++            // from 0 to 5: pair of segment corner coordinates
++            //
++            // segment corner indices are these:
++            //  
++            //   0 - 1
++            //   |   |
++            //   2 - 3
++            //   |   |
++            //   4 - 5
++            //  
++            static const double corners[] = 
++            { 
++                fLeft,  fTop,
++                fRight, fTop,
++                fLeft,  fMiddle,
++                fRight, fMiddle,
++                fLeft,  fBottom,
++                fRight, fBottom
++            };
++
++            // from 0 to 9: which segments are 'lit' for this number?
++            //
++            // array denotes graph edges to traverse, with -1 means
++            // stop (the vertices are the corner indices from above):
++            //     0
++            //     -
++            // 1 |   | 2
++            //     - 3
++            // 4 |   | 5
++            //     -
++            //     6
++            //
++            static const int numbers[] =
++            {
++                1, 1, 1, 0, 1, 1, 1, // 0
++                0, 0, 1, 0, 0, 1, 0, // 1
++                1, 0, 1, 1, 1, 0, 1, // 2
++                1, 0, 1, 1, 0, 1, 1, // 3
++                0, 1, 1, 1, 0, 1, 0, // 4
++                1, 1, 0, 1, 0, 1, 1, // 5
++                1, 1, 0, 1, 1, 1, 1, // 6
++                1, 0, 1, 0, 0, 1, 0, // 1
++                1, 1, 1, 1, 1, 1, 1, // 8
++                1, 1, 1, 1, 0, 1, 1, // 9
++                0, 0, 0, 1, 0, 0, 0, // '-'
++                1, 1, 0, 1, 1, 0, 1, // 'E'
++            };
++
++            // maps segment index to two corner ids:
++            static const int index2corner[] =
++            {
++                0, 2,  // 0
++                0, 4,  // 1
++                2, 6,  // 2
++                4, 6,  // 3
++                4, 8,  // 4
++                6, 10, // 5
++                8, 10, // 6
++            };
++
++            B2DPolyPolygon aRes;
++            if( nNumber == '-' )
++            {
++                nNumber = 10;
++            }
++            else if( nNumber == 'E' )
++            {
++                nNumber = 11;
++            }
++            else if( nNumber == '.' )
++            {
++                if( bLitSegments )
++                    aRes.append(createPolygonFromCircle(B2DPoint(fTotalSize/2, fTotalSize), 
++                                                        fSegmentEndChopHoriz));
++                return aRes;
++            }
++            else
++            {
++                nNumber=clamp<sal_uInt32>(nNumber,'0','9') - '0';
++            }
++
++            B2DPolygon aCurrSegment;
++            const size_t sliceSize=sizeof(numbers)/sizeof(*numbers)/12;
++            const int* pCurrSegment=numbers + nNumber*sliceSize;
++            for( size_t i=0; i<sliceSize; i++, pCurrSegment++)
++            {
++                if( !(*pCurrSegment ^ bLitSegments) )
++                {
++                    const size_t j=2*i;
++                    aCurrSegment.clear();
++                    B2DPoint start(corners[index2corner[j]],   
++                                   corners[index2corner[j]+1]  );
++                    B2DPoint end  (corners[index2corner[j+1]], 
++                                   corners[index2corner[j+1]+1]);
++
++                    if( start.getX() == end.getX() )
++                    {
++                        start.setY(start.getY()+fSegmentEndChopVert);
++                        end.setY(end.getY()-fSegmentEndChopVert);
++                    }
++                    else
++                    {
++                        start.setX(start.getX()+fSegmentEndChopHoriz);
++                        end.setX(end.getX()-fSegmentEndChopHoriz);
++                    }
++
++                    aCurrSegment.append(start);
++                    aCurrSegment.append(end);
++                }
++                aRes.append(aCurrSegment);
++            }
++
++            return aRes;
++        }
++
+ 	} // end of namespace tools
+ } // end of namespace basegfx
+ 
+diff --git basegfx/source/tools/makefile.mk basegfx/source/tools/makefile.mk
+index df75a82..22b8e5c 100755
+--- basegfx/source/tools/makefile.mk
++++ basegfx/source/tools/makefile.mk
+@@ -45,6 +45,7 @@ SLOFILES= $(SLO)$/canvastools.obj	\
+ 		  $(SLO)$/gradienttools.obj	\
+ 		  $(SLO)$/debugplotter.obj	\
+ 		  $(SLO)$/liangbarsky.obj	\
++		  $(SLO)$/numbertools.obj	\
+ 		  $(SLO)$/tools.obj		    \
+ 		  $(SLO)$/unopolypolygon.obj
+ 
+diff --git basegfx/source/tools/numbertools.cxx basegfx/source/tools/numbertools.cxx
+new file mode 100644
+index 0000000..91520c2
+--- /dev/null
++++ basegfx/source/tools/numbertools.cxx
+@@ -0,0 +1,79 @@
++/*************************************************************************
++ *
++ * 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: b2dpolypolygontools.hxx,v $
++ * $Revision: 1.20 $
++ *
++ * 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.
++ *
++ ************************************************************************/
++
++#include <basegfx/tools/tools.hxx> 
++#include <basegfx/matrix/b2dhommatrix.hxx> 
++#include <basegfx/polygon/b2dpolypolygon.hxx> 
++#include <basegfx/polygon/b2dpolypolygontools.hxx> 
++
++#include <rtl/ustrbuf.hxx>
++#include <rtl/math.hxx>
++
++#include <utility>
++
++namespace basegfx { namespace tools
++{
++    B2DPolyPolygon number2PolyPolygon(double fValue, sal_Int32 nTotalDigits, sal_Int32 nDecPlaces, bool bLitSegments)
++    {
++        // config here
++        // {
++        const double fSpace=0.2;
++        // }
++        // config here
++
++        rtl::OUStringBuffer aNum;
++        rtl::math::doubleToUStringBuffer(aNum,
++                                         fValue, 
++                                         rtl_math_StringFormat_F, 
++                                         nDecPlaces, '.', 
++                                         0, ',');
++
++        B2DPolyPolygon aRes;
++        B2DHomMatrix aMat;
++        double fCurrX=std::max(nTotalDigits-aNum.getLength(), 0) * (1.0+fSpace);
++        for( sal_Int32 i=0; i<aNum.getLength(); ++i )
++        {
++            B2DPolyPolygon aCurr;
++            aCurr=createSevenSegmentPolyPolygon(aNum.charAt(i), 
++                                                bLitSegments);
++            
++            aMat.identity();
++            aMat.translate(fCurrX,0.0);
++            aCurr.transform(aMat);
++
++            fCurrX += 1.0+fSpace;
++
++            aRes.append(aCurr);
++        }
++        
++        return aRes;
++    }
++
++} }
 diff --git canvas/prj/build.lst canvas/prj/build.lst
 index df1f8e9..3f94041 100644
 --- canvas/prj/build.lst
@@ -170,10 +569,10 @@
 +};
 diff --git canvas/source/opengl/makefile.mk canvas/source/opengl/makefile.mk
 new file mode 100644
-index 0000000..c446e16
+index 0000000..90fb7ea
 --- /dev/null
 +++ canvas/source/opengl/makefile.mk
-@@ -0,0 +1,66 @@
+@@ -0,0 +1,67 @@
 +#*************************************************************************
 +#
 +#    OpenOffice.org - a multi-platform office productivity suite
@@ -206,13 +605,14 @@
 +CDEFS+= -DVERBOSE
 +.ENDIF
 +
-+SLOFILES =	$(SLO)$/ogl_spritecanvas.obj \
-+			$(SLO)$/ogl_spritedevicehelper.obj \
-+			$(SLO)$/ogl_canvashelper.obj \
-+			$(SLO)$/ogl_canvasfont.obj \
++SLOFILES =	$(SLO)$/ogl_bitmapcanvashelper.obj \
 +			$(SLO)$/ogl_canvasbitmap.obj \
-+			$(SLO)$/ogl_bitmapcanvashelper.obj \
 +			$(SLO)$/ogl_canvascustomsprite.obj \
++			$(SLO)$/ogl_canvasfont.obj \
++			$(SLO)$/ogl_canvashelper.obj \
++			$(SLO)$/ogl_canvastools.obj \
++			$(SLO)$/ogl_spritecanvas.obj \
++			$(SLO)$/ogl_spritedevicehelper.obj \
 +			$(SLO)$/ogl_textlayout.obj \
 +			$(SLO)$/ogl_texturecache.obj
 +
@@ -467,6 +867,50 @@
 +}
 +
 +#endif
+diff --git canvas/source/opengl/ogl_buffercontext.hxx canvas/source/opengl/ogl_buffercontext.hxx
+new file mode 100644
+index 0000000..7cc2311
+--- /dev/null
++++ canvas/source/opengl/ogl_buffercontext.hxx
+@@ -0,0 +1,38 @@
++/*************************************************************************
++ *
++ *    OpenOffice.org - a multi-platform office productivity suite
++ *
++ *    Author:
++ *      Thorsten Behrens <tbehrens novell com>      
++ *
++ *      Copyright (C) 2008, Novell Inc.
++ *      Parts copyright 2005 by Sun Microsystems, Inc.
++ *
++ *   The Contents of this file are made available subject to
++ *   the terms of GNU Lesser General Public License Version 2.1.
++ *
++ ************************************************************************/
++
++#ifndef OGL_BUFFERCONTEXT_HXX_
++#define OGL_BUFFERCONTEXT_HXX_
++
++#include <sal/config.h>
++#include <boost/shared_ptr.hpp>
++
++namespace oglcanvas
++{
++    struct IBufferContext
++    {
++        virtual ~IBufferContext() {}
++
++        /// start render to buffer. changes gl current context
++        virtual bool startBufferRendering() = 0;
++
++        /// end render to buffer. switches to window context, and selects rendered texture
++        virtual bool endBufferRendering() = 0;
++    };
++
++    typedef ::boost::shared_ptr<IBufferContext> IBufferContextSharedPtr;
++}
++
++#endif
 diff --git canvas/source/opengl/ogl_canvasbitmap.cxx canvas/source/opengl/ogl_canvasbitmap.cxx
 new file mode 100644
 index 0000000..9853461
@@ -626,10 +1070,10 @@
 +#endif
 diff --git canvas/source/opengl/ogl_canvascustomsprite.cxx canvas/source/opengl/ogl_canvascustomsprite.cxx
 new file mode 100644
-index 0000000..2d88417
+index 0000000..29bcc51
 --- /dev/null
 +++ canvas/source/opengl/ogl_canvascustomsprite.cxx
-@@ -0,0 +1,154 @@
+@@ -0,0 +1,226 @@
 +/*************************************************************************
 + *
 + *    OpenOffice.org - a multi-platform office productivity suite
@@ -649,6 +1093,7 @@
 +#include "precompiled_canvas.hxx"
 +
 +#include "ogl_canvascustomsprite.hxx"
++#include "ogl_canvastools.hxx"
 +#include "ogl_tools.hxx"
 +
 +#include <canvas/debug.hxx>
@@ -676,6 +1121,7 @@
 +                                            SpriteDeviceHelper&                           rDeviceHelper ) :
 +        mpSpriteCanvas( rRefDevice ),
 +        maSize(rSpriteSize),
++        mxClip(),
 +        maTransformation(),
 +        maPosition(),
 +        mfAlpha(0.0),
@@ -684,6 +1130,7 @@
 +        ENSURE_OR_THROW( rRefDevice.get(),
 +                         "CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" );
 +
++        ::canvas::tools::setIdentityAffineMatrix2D(maTransformation);
 +        maCanvasHelper.init( *rRefDevice.get(),
 +                             rDeviceHelper );
 +    }
@@ -731,9 +1178,9 @@
 +        maTransformation = aTransformation;
 +    }
 +
-+    void SAL_CALL CanvasCustomSprite::clip( const uno::Reference< rendering::XPolyPolygon2D >& /*aClip*/ ) throw (uno::RuntimeException)
++    void SAL_CALL CanvasCustomSprite::clip( const uno::Reference< rendering::XPolyPolygon2D >& xClip ) throw (uno::RuntimeException)
 +    {
-+        // TODO(F3)
++        mxClip = xClip;
 +    }
 +
 +    void SAL_CALL CanvasCustomSprite::setPriority( double nPriority ) throw (uno::RuntimeException)
@@ -763,33 +1210,102 @@
 +
 +    bool CanvasCustomSprite::renderSprite() const
 +    {
-+        TransformationPreserver aPreserver;
++        if( ::basegfx::fTools::equalZero( mfAlpha ) )
++            return true;
++
++        TransformationPreserver aPreserver1;
++        const ::basegfx::B2IVector aSpriteSizePixel(
++            ::canvas::tools::roundUp( maSize.Width ),
++            ::canvas::tools::roundUp( maSize.Height ));
 +
 +        // translate sprite to output position
 +        glTranslated(maPosition.getX(), maPosition.getY(), 0);
 +
-+        // apply sprite content transformation matrix
-+        double aGLTransform[] = 
++        {
++            TransformationPreserver aPreserver2;
++
++            // apply sprite content transformation matrix
++            double aGLTransform[] = 
++                {
++                    maTransformation.m00, maTransformation.m10, 0, 0,
++                    maTransformation.m01, maTransformation.m11, 0, 0,
++                    0,                    0,                    1, 0,
++                    maTransformation.m02, maTransformation.m12, 0, 1
++                };
++            glMultMatrixd(aGLTransform);
++
++            IBufferContextSharedPtr pBufferContext;
++            if( mfAlpha != 1.0 || mxClip.is() )
 +            {
-+                maTransformation.m00, maTransformation.m10, 0, 0,
-+                maTransformation.m01, maTransformation.m11, 0, 0,
-+                0,                    0,                    1, 0,
-+                maTransformation.m02, maTransformation.m12, 0, 1
-+            };
-+        glMultMatrixd(aGLTransform);
++                // drats. need to render to temp surface before, and then   
++                // composite that to screen 
++                pBufferContext=maCanvasHelper.getDeviceHelper()->createBufferContext(aSpriteSizePixel);
++                pBufferContext->startBufferRendering();
++            }
 +
-+        if( !maCanvasHelper.renderRecordedActions() )
-+            return false;
++            // this ends up in pBufferContext, if that one's "current"
++            if( !maCanvasHelper.renderRecordedActions() )
++                return false;
++
++            if( pBufferContext )
++            {
++                // content ended up in background buffer - compose to
++                // screen now. Calls below switches us back to window
++                // context, and binds to generated, dynamic texture
++                pBufferContext->endBufferRendering();
++
++                glEnable(GL_TEXTURE_2D);
++                glTexParameteri(GL_TEXTURE_2D,
++                                GL_TEXTURE_MIN_FILTER,
++                                GL_NEAREST);
++                glTexParameteri(GL_TEXTURE_2D,
++                                GL_TEXTURE_MAG_FILTER,
++                                GL_NEAREST);
++                glEnable(GL_BLEND);
++                glBlendFunc(GL_SRC_ALPHA, 
++                            GL_ONE_MINUS_SRC_ALPHA);
++
++                // blend against fixed vertex color; texture alpha is multiplied in
++                glColor4f(1,1,1,mfAlpha); 
++
++                // if( mxClip ) - TODO clipping
++                glBegin(GL_TRIANGLE_STRIP);
++                glTexCoord2f(0,0);                        glVertex2d(0,0);
++                glTexCoord2f(0,maSize.Height);            glVertex2d(0, aSpriteSizePixel.getY());
++                glTexCoord2f(maSize.Width,0);             glVertex2d(aSpriteSizePixel.getX(),0);
++                glTexCoord2f(maSize.Width,maSize.Height); glVertex2d(aSpriteSizePixel.getX(),aSpriteSizePixel.getY());
++                glEnd();
++
++                glBindTexture(GL_TEXTURE_2D, 0);
++                glDisable(GL_TEXTURE_2D);
++            }
++        }
++
++        glColor4f(1,0,0,1);
++        glBegin(GL_LINE_STRIP);
++        glVertex2d(-2,-2);
++        glVertex2d(-2,maSize.Height+4);
++        glVertex2d(maSize.Width+4,maSize.Height+4);
++        glVertex2d(maSize.Width+4,-2);
++        glVertex2d(-2,-2);
++        glVertex2d(maSize.Width+4,maSize.Height+4);
++        glEnd();
++
++        std::vector<double> aVec; 
++        aVec.push_back(mfAlpha);
++        aVec.push_back(mfPriority);
++        aVec.push_back(maCanvasHelper.getRecordedActionCount());
++        renderOSD( aVec, 10 );
 +
 +        return true;
 +    }
 +}
 diff --git canvas/source/opengl/ogl_canvascustomsprite.hxx canvas/source/opengl/ogl_canvascustomsprite.hxx
 new file mode 100644
-index 0000000..7d0b4bf
+index 0000000..82f3777
 --- /dev/null
 +++ canvas/source/opengl/ogl_canvascustomsprite.hxx
-@@ -0,0 +1,101 @@
+@@ -0,0 +1,103 @@
 +/*************************************************************************
 + *
 + *    OpenOffice.org - a multi-platform office productivity suite
@@ -883,10 +1399,12 @@
 +        SpriteCanvasRef                              mpSpriteCanvas;
 +        const ::com::sun::star::geometry::RealSize2D maSize;
 +
-+        ::com::sun::star::geometry::AffineMatrix2D   maTransformation;
-+        ::basegfx::B2DPoint                          maPosition;
-+        double                                       mfAlpha;
-+        double                                       mfPriority;
++        ::com::sun::star::uno::Reference< 
++            ::com::sun::star::rendering::XPolyPolygon2D > mxClip;
++        ::com::sun::star::geometry::AffineMatrix2D        maTransformation;
++        ::basegfx::B2DPoint                               maPosition;
++        double                                            mfAlpha;
++        double                                            mfPriority;
 +    };
 +}
 +
@@ -1065,10 +1583,10 @@
 +#endif
 diff --git canvas/source/opengl/ogl_canvashelper.cxx canvas/source/opengl/ogl_canvashelper.cxx
 new file mode 100644
-index 0000000..93673db
+index 0000000..5b05591
 --- /dev/null
 +++ canvas/source/opengl/ogl_canvashelper.cxx
-@@ -0,0 +1,1092 @@
+@@ -0,0 +1,1019 @@
 +/*************************************************************************
 + *
 + *    OpenOffice.org - a multi-platform office productivity suite
@@ -1111,6 +1629,7 @@
 +#include <vcl/font.hxx>
 +
 +#include "ogl_canvasfont.hxx"
++#include "ogl_canvastools.hxx"
 +#include "ogl_canvasbitmap.hxx"
 +#include "ogl_spritecanvas.hxx"
 +#include "ogl_texturecache.hxx"
@@ -1177,81 +1696,6 @@
 +
 +    namespace
 +    {
-+        /// triangulates polygon before
-+        void renderComplexPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly )
-+        {
-+            ::basegfx::B2DPolyPolygon aPolyPoly(rPolyPoly);
-+            if( aPolyPoly.areControlPointsUsed() )
-+                aPolyPoly = rPolyPoly.getDefaultAdaptiveSubdivision();
-+            const ::basegfx::B2DRange& rBounds(aPolyPoly.getB2DRange());
-+            const double nWidth=rBounds.getWidth();
-+            const double nHeight=rBounds.getHeight();
-+            const ::basegfx::B2DPolygon& rTriangulatedPolygon(
-+                ::basegfx::triangulator::triangulate(aPolyPoly));
-+
-+            for( sal_uInt32 i=0; i<rTriangulatedPolygon.count(); i++ ) 
-+            {
-+                const ::basegfx::B2DPoint& rPt( rTriangulatedPolygon.getB2DPoint(i) );
-+				const double s(rPt.getX()/nWidth);
-+                const double t(rPt.getY()/nHeight);
-+                glTexCoord2f(s,t); glVertex2d(rPt.getX(), rPt.getY());
-+            }
-+        }
-+
-+        /** only use this for line polygons. 
-+
-+            better not leave triangulation to OpenGL. also, ignores texturing
-+          */
-+        void renderPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly )
-+        {
-+            ::basegfx::B2DPolyPolygon aPolyPoly(rPolyPoly);
-+            if( aPolyPoly.areControlPointsUsed() )
-+                aPolyPoly = rPolyPoly.getDefaultAdaptiveSubdivision();
-+
-+            for( sal_uInt32 i=0; i<aPolyPoly.count(); i++ ) 
-+            {
-+                const ::basegfx::B2DPolygon& rPolygon( aPolyPoly.getB2DPolygon(i) );
-+
-+                const sal_uInt32 nPts=rPolygon.count();
-+                const sal_uInt32 nExtPts=nPts + rPolygon.isClosed();
-+                for( sal_uInt32 j=0; j<nExtPts; j++ ) 
-+                {
-+                    const ::basegfx::B2DPoint& rPt( rPolygon.getB2DPoint( j % nPts ) );
-+                    glVertex2d(rPt.getX(), rPt.getY());
-+                }
-+            }
-+        }
-+        
-+        void setupState( const ::basegfx::B2DHomMatrix&   rTransform,
-+                         GLenum                           eSrcBlend,
-+                         GLenum                           eDstBlend,
-+                         const rendering::ARGBColor&      rColor )
-+        {
-+            double aGLTransform[] = 
-+                {
-+                    rTransform.get(0,0), rTransform.get(1,0), 0, 0,
-+                    rTransform.get(0,1), rTransform.get(1,1), 0, 0,
-+                    0,                   0,                   1, 0,
-+                    rTransform.get(0,2), rTransform.get(1,2), 0, 1
-+                };
-+            glMultMatrixd(aGLTransform);
-+
-+            glEnable(GL_BLEND);
-+            glBlendFunc(eSrcBlend, eDstBlend);
-+
-+            glColor4d(rColor.Red,
-+                      rColor.Green,
-+                      rColor.Blue,
-+                      rColor.Alpha);
-+
-+            // GL 1.2:
-+            // glBlendEquation( GLenum mode );
-+            // glBlendColor( GLclampf red, GLclampf green,GLclampf blue, GLclampf alpha );
-+            // glConvolutionFilter1D
-+            // glConvolutionFilter2D
-+            // glSeparableFilter2D
-+        }
-+
 +        bool lcl_drawPoint( const CanvasHelper&              /*rHelper*/,
 +                            const ::basegfx::B2DHomMatrix&   rTransform,
 +                            GLenum                           eSrcBlend,
@@ -1301,11 +1745,7 @@
 +            ::basegfx::B2DPolyPolygonVector::const_iterator aCurr=rPolyPolygons.begin();
 +            const ::basegfx::B2DPolyPolygonVector::const_iterator aEnd=rPolyPolygons.end();
 +            while( aCurr != aEnd )
-+            {
-+                glBegin(GL_LINE_STRIP);
 +                renderPolyPolygon(*aCurr++);
-+                glEnd();
-+            }
 +
 +            return true;
 +        }
@@ -1512,7 +1952,7 @@
 +            glLoadMatrixd(aTexTransform);
 +
 +            // blend against fixed vertex color; texture alpha is multiplied in
-+            glColor4f(1,1,1,1); 
++            glColor4f(1,1,1,rTexture.Alpha); 
 +
 +            aCurr=rPolyPolygons.begin();
 +            while( aCurr != aEnd )
@@ -2160,13 +2600,18 @@
 +
 +        return true;
 +    }
++
++    size_t CanvasHelper::getRecordedActionCount() const
++    {
++        return mpRecordedActions->size();
++    }
 +}
 diff --git canvas/source/opengl/ogl_canvashelper.hxx canvas/source/opengl/ogl_canvashelper.hxx
 new file mode 100644
-index 0000000..fafd450
+index 0000000..7ac6bd8
 --- /dev/null
 +++ canvas/source/opengl/ogl_canvashelper.hxx
-@@ -0,0 +1,238 @@
+@@ -0,0 +1,242 @@
 +/*************************************************************************
 + *
 + *    OpenOffice.org - a multi-platform office productivity suite
@@ -2368,6 +2813,10 @@
 +         */
 +        bool renderRecordedActions() const;
 +
++        /** Retrieve number of recorded actions
++         */
++        size_t getRecordedActionCount() const;
++
 +        SpriteDeviceHelper* getDeviceHelper() const { return mpDeviceHelper; }
 +        ::com::sun::star::rendering::XGraphicDevice* getDevice() const { return mpDevice; }
 +
@@ -2405,6 +2854,206 @@
 +}
 +
 +#endif
+diff --git canvas/source/opengl/ogl_canvastools.cxx canvas/source/opengl/ogl_canvastools.cxx
+new file mode 100644
+index 0000000..17f9b16
+--- /dev/null
++++ canvas/source/opengl/ogl_canvastools.cxx
+@@ -0,0 +1,147 @@
++/*************************************************************************
++ *
++ *    OpenOffice.org - a multi-platform office productivity suite
++ *
++ *    Author:
++ *      Thorsten Behrens <tbehrens novell com>      
++ *
++ *      Copyright (C) 2008, Novell Inc.
++ *      Parts copyright 2005 by Sun Microsystems, Inc.
++ *      Parts copyright 2004 David Reveman, Peter Nilsson
++ *
++ *   The Contents of this file are made available subject to
++ *   the terms of GNU Lesser General Public License Version 2.1.
++ *
++ ************************************************************************/
++
++// MARKER(update_precomp.py): autogen include statement, do not remove
++#include "precompiled_canvas.hxx"
++
++#define GL_GLEXT_PROTOTYPES
++
++#include "ogl_canvastools.hxx"
++
++#include <canvas/debug.hxx>
++#include <tools/diagnose_ex.h>
++#include <basegfx/tools/canvastools.hxx>
++#include <basegfx/matrix/b2dhommatrix.hxx>
++#include <basegfx/tools/tools.hxx>
++#include <basegfx/polygon/b2dpolypolygon.hxx>
++#include <basegfx/polygon/b2dpolygontriangulator.hxx>
++#include <basegfx/polygon/b2dpolypolygontools.hxx>
++
++#include <com/sun/star/rendering/ARGBColor.hpp>
++
++#include <GL/gl.h>
++#include <GL/glu.h>
++#include <GL/glext.h>
++
++
++using namespace ::com::sun::star;
++
++namespace oglcanvas
++{
++    /// triangulates polygon before
++    void renderComplexPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly )
++    {
++        ::basegfx::B2DPolyPolygon aPolyPoly(rPolyPoly);
++        if( aPolyPoly.areControlPointsUsed() )
++            aPolyPoly = rPolyPoly.getDefaultAdaptiveSubdivision();
++        const ::basegfx::B2DRange& rBounds(aPolyPoly.getB2DRange());
++        const double nWidth=rBounds.getWidth();
++        const double nHeight=rBounds.getHeight();
++        const ::basegfx::B2DPolygon& rTriangulatedPolygon(
++            ::basegfx::triangulator::triangulate(aPolyPoly));
++
++        for( sal_uInt32 i=0; i<rTriangulatedPolygon.count(); i++ ) 
++        {
++            const ::basegfx::B2DPoint& rPt( rTriangulatedPolygon.getB2DPoint(i) );
++            const double s(rPt.getX()/nWidth);
++            const double t(rPt.getY()/nHeight);
++            glTexCoord2f(s,t); glVertex2d(rPt.getX(), rPt.getY());
++        }
++    }
++
++    /** only use this for line polygons. 
++
++        better not leave triangulation to OpenGL. also, ignores texturing
++    */
++    void renderPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly )
++    {
++        ::basegfx::B2DPolyPolygon aPolyPoly(rPolyPoly);
++        if( aPolyPoly.areControlPointsUsed() )
++            aPolyPoly = rPolyPoly.getDefaultAdaptiveSubdivision();
++
++        for( sal_uInt32 i=0; i<aPolyPoly.count(); i++ ) 
++        {
++            glBegin(GL_LINE_STRIP);
++
++            const ::basegfx::B2DPolygon& rPolygon( aPolyPoly.getB2DPolygon(i) );
++
++            const sal_uInt32 nPts=rPolygon.count();
++            const sal_uInt32 nExtPts=nPts + rPolygon.isClosed();
++            for( sal_uInt32 j=0; j<nExtPts; j++ ) 
++            {
++                const ::basegfx::B2DPoint& rPt( rPolygon.getB2DPoint( j % nPts ) );
++                glVertex2d(rPt.getX(), rPt.getY());
++            }
++
++            glEnd();
++        }
++    }
++        
++    void setupState( const ::basegfx::B2DHomMatrix&   rTransform,
++                     GLenum                           eSrcBlend,
++                     GLenum                           eDstBlend,
++                     const rendering::ARGBColor&      rColor )
++    {
++        double aGLTransform[] = 
++            {
++                rTransform.get(0,0), rTransform.get(1,0), 0, 0,
++                rTransform.get(0,1), rTransform.get(1,1), 0, 0,
++                0,                   0,                   1, 0,
++                rTransform.get(0,2), rTransform.get(1,2), 0, 1
++            };
++        glMultMatrixd(aGLTransform);
++
++        glEnable(GL_BLEND);
++        glBlendFunc(eSrcBlend, eDstBlend);
++
++        glColor4d(rColor.Red,
++                  rColor.Green,
++                  rColor.Blue,
++                  rColor.Alpha);
++
++        // GL 1.2:
++        // glBlendEquation( GLenum mode );
++        // glBlendColor( GLclampf red, GLclampf green,GLclampf blue, GLclampf alpha );
++        // glConvolutionFilter1D
++        // glConvolutionFilter2D
++        // glSeparableFilter2D
++    }
++
++    void renderOSD( const std::vector<double>& rNumbers, double scale )
++    {
++        double y=4.0;
++        basegfx::B2DHomMatrix aTmp;
++        basegfx::B2DHomMatrix aScaleShear;
++        aScaleShear.shearX(-0.1);
++        aScaleShear.scale(scale,scale);
++
++        for( size_t i=0; i<rNumbers.size(); ++i )
++        {
++            aTmp.identity();
++            aTmp.translate(0,y);
++            y += 1.2*scale;
++
++            basegfx::B2DPolyPolygon aPoly=
++                basegfx::tools::number2PolyPolygon(rNumbers[i],10,3);
++
++            aTmp=aTmp*aScaleShear;
++            aPoly.transform(aTmp);
++            
++            glColor4f(0,1,0,1);
++            renderPolyPolygon(aPoly);
++        }
++    }
++}
+diff --git canvas/source/opengl/ogl_canvastools.hxx canvas/source/opengl/ogl_canvastools.hxx
+new file mode 100644
+index 0000000..69aa0c7
+--- /dev/null
++++ canvas/source/opengl/ogl_canvastools.hxx
+@@ -0,0 +1,41 @@
++/*************************************************************************
++ *
++ *    OpenOffice.org - a multi-platform office productivity suite
++ *
++ *    Author:
++ *      Thorsten Behrens <tbehrens novell com>      
++ *
++ *      Copyright (C) 2008, Novell Inc.
++ *
++ *   The Contents of this file are made available subject to
++ *   the terms of GNU Lesser General Public License Version 2.1.
++ *
++ ************************************************************************/
++
++#ifndef OGL_CANVASTOOLS_HXX
++#define OGL_CANVASTOOLS_HXX
++
++#include <sal/config.h>
++#include <vector>
++
++namespace com { namespace sun { namespace star { namespace rendering {
++    struct ARGBColor;
++}}}}
++namespace basegfx {
++    class B2DPolyPolygon;
++    class B2DHomMatrix;
++}
++
++namespace oglcanvas
++{
++    void renderComplexPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly );
++    void renderPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly );
++    void setupState( const ::basegfx::B2DHomMatrix&                rTransform,
++                     unsigned int                                  eSrcBlend,
++                     unsigned int                                  eDstBlend,
++                     const ::com::sun::star::rendering::ARGBColor& rColor );
++
++    void renderOSD( const std::vector<double>& rNumbers, double scale );
++}
++
++#endif
 diff --git canvas/source/opengl/ogl_spritecanvas.cxx canvas/source/opengl/ogl_spritecanvas.cxx
 new file mode 100644
 index 0000000..275adbc
@@ -2747,10 +3396,10 @@
 +#endif
 diff --git canvas/source/opengl/ogl_spritedevicehelper.cxx canvas/source/opengl/ogl_spritedevicehelper.cxx
 new file mode 100644
-index 0000000..2ac2122
+index 0000000..7d7e6ec
 --- /dev/null
 +++ canvas/source/opengl/ogl_spritedevicehelper.cxx
-@@ -0,0 +1,774 @@
+@@ -0,0 +1,991 @@
 +/*************************************************************************
 + *
 + *    OpenOffice.org - a multi-platform office productivity suite
@@ -2773,6 +3422,7 @@
 +#include "ogl_spritedevicehelper.hxx"
 +#include "ogl_spritecanvas.hxx"
 +#include "ogl_canvasbitmap.hxx"
++#include "ogl_canvastools.hxx"
 +#include "ogl_canvascustomsprite.hxx"
 +#include "ogl_texturecache.hxx"
 +
@@ -2859,7 +3509,7 @@
 +    "{                                                                          "
 +	"    gl_FragColor = mix(v_startColor4d,                                     "
 +    "                       v_endColor4d,                                       "
-+    "                       distance(                                           "
++    "                       1.0 - distance(                                     "
 +    "                          vec2(                                            "
 +    "                             m_transform * vec3(v_textureCoords2d,1)),     "
 +    "                          v_center2d));                                    "
@@ -2875,18 +3525,170 @@
 +    "uniform vec4   v_endColor4d;                                               "
 +    "uniform mat3x2 m_transform;                                                "
 +    "varying vec2   v_textureCoords2d;                                          "
-+    "const vec2     v_center2d = vec2(0,0);                                     "
 +    "void main(void)                                                            "
 +    "{                                                                          "
++    "    const vec2 v = abs( vec2(m_transform * vec3(v_textureCoords2d,1)) );   "
++    "    const float t = max(v.x, v.y);                                         "
 +	"    gl_FragColor = mix(v_startColor4d,                                     "
 +    "                       v_endColor4d,                                       "
-+    "                       distance(                                           "
-+    "                          vec2(                                            "
-+    "                             m_transform * vec3(v_textureCoords2d,1)),     "
-+    "                          v_center2d));                                    "
++    "                       1.0-t);                                             "
 +    "}                                                                          "
 +};
 +
++static void initContext()
++{
++    // need the backside for mirror effects
++    glDisable(GL_CULL_FACE);
++
++    // no perspective, we're 2D 
++    glMatrixMode(GL_PROJECTION);
++    glLoadIdentity();
++
++    // misc preferences
++    glEnable(GL_POINT_SMOOTH);
++    glEnable(GL_LINE_SMOOTH);
++    glEnable(GL_POLYGON_SMOOTH);
++    glHint(GL_POINT_SMOOTH_HINT,GL_NICEST);
++    glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
++    glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);
++    glShadeModel(GL_FLAT);
++}
++
++static void initTransformation(const ::Size& rSize)
++{
++    // use whole window
++    glViewport( 0,0,
++                (GLsizei)rSize.Width(),
++                (GLsizei)rSize.Height() );
++
++    // model coordinate system is already in device pixel
++    glMatrixMode(GL_MODELVIEW);
++    glLoadIdentity();
++    glTranslated(-1.0, 1.0, 0.0);
++    glScaled( 2.0  / rSize.Width(), 
++              -2.0 / rSize.Height(), 
++              1.0 );
++
++    // clear to black
++    glClearColor(0,0,0,0);
++    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
++}
++
++static boost::shared_ptr<SystemChildWindow> createChildWindow( unx::XVisualInfo*& viWin,
++                                                               unx::XVisualInfo*& viPB,
++                                                               void*&             fbConfig,
++                                                               Window&            rWindow,
++                                                               unx::Display*      pDisplay,
++                                                               int                nScreen )
++{
++    // select appropriate visual    
++    static int attrList3[] =
++        {
++            GLX_RGBA,//only TrueColor or DirectColor
++            //single buffered
++            GLX_RED_SIZE,4,//use the maximum red bits, with a minimum of 4 bits
++            GLX_GREEN_SIZE,4,//use the maximum green bits, with a minimum of 4 bits
++            GLX_BLUE_SIZE,4,//use the maximum blue bits, with a minimum of 4 bits
++            GLX_DEPTH_SIZE,0,//no depth buffer
++            None
++        };
++    static int attrList2[] = 
++        {
++            GLX_RGBA,//only TrueColor or DirectColor
++            /// single buffered
++            GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
++            GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
++            GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
++            GLX_DEPTH_SIZE,1,/// use the maximum depth bits, making sure there is a depth buffer
++            None
++        };
++    static int attrList1[] =
++        {
++            GLX_RGBA,//only TrueColor or DirectColor
++            GLX_DOUBLEBUFFER,/// only double buffer
++            GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
++            GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
++            GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
++            GLX_DEPTH_SIZE,0,/// no depth buffer
++            None
++        };
++    static int attrList0[] =
++        {
++            GLX_RGBA,//only TrueColor or DirectColor
++            GLX_DOUBLEBUFFER,// only double buffer
++            GLX_RED_SIZE,4,// use the maximum red bits, with a minimum of 4 bits
++            GLX_GREEN_SIZE,4,// use the maximum green bits, with a minimum of 4 bits
++            GLX_BLUE_SIZE,4,// use the maximum blue bits, with a minimum of 4 bits
++            GLX_DEPTH_SIZE,1,// use the maximum depth bits, making sure there is a depth buffer
++            None
++        }; 
++    static int* attrTable[] = 
++        {
++            attrList0,
++            attrList1,
++            attrList2,
++            attrList3,
++            NULL
++        };
++    int** pAttributeTable = attrTable;
++
++    boost::shared_ptr<SystemChildWindow> pResult;
++    unx::GLXFBConfig* fbConfigs=NULL;
++    int nConfigs, nVal;
++    while( *pAttributeTable )
++    {
++        // try to find a window visual for the current set of
++        // attributes
++        viWin = unx::glXChooseVisual( pDisplay,
++                                      nScreen,
++                                      *pAttributeTable );
++        if( viWin ) 
++        {
++            // try to find a framebuffer config for the current set of
++            // attributes
++            fbConfigs = unx::glXGetFBConfigs(pDisplay, nScreen, &nConfigs);
++            for(int i=0; i<nConfigs; i++)
++            {
++                viPB = glXGetVisualFromFBConfig(pDisplay, fbConfigs[i]);
++                if( viPB && viPB->visualid != viWin->visualid )
++                {
++                    glXGetFBConfigAttrib(pDisplay, 
++                                         fbConfigs[i], 
++                                         GLX_DRAWABLE_TYPE, 
++                                         &nVal);
++
++                    if( (GLX_PBUFFER_BIT|GLX_WINDOW_BIT|GLX_PIXMAP_BIT) 
++                        == (nVal & (GLX_PBUFFER_BIT|GLX_WINDOW_BIT|GLX_PIXMAP_BIT)) )
++                    {                        
++                        SystemWindowData winData;
++                        winData.nSize = sizeof(winData);
++                        OSL_TRACE("using VisualID %08X for OpenGL canvas", viWin->visualid);
++                        winData.pVisual = (void*)(viWin->visual);
++                        pResult.reset( new SystemChildWindow(&rWindow, 0, &winData, FALSE) );
++
++                        if( pResult->GetSystemData() )
++                        {
++                            fbConfig = &fbConfigs[i];
++                            return pResult;
++                        }
++
++                        pResult.reset();
++                    }
++                        
++                    XFree(viPB);
++                }
++            }
++                
++            XFree(viWin);
++        }
++
++        ++pAttributeTable;
++    }
++        
++    return pResult;
++}
++
++
 +namespace oglcanvas
 +{
 +    /** Compile shader program
@@ -2948,9 +3750,12 @@
 +        mpDevice(NULL),
 +        mpSpriteCanvas(NULL),
 +        maActiveSprites(),
++        maLastUpdate(),
 +        mpChildWindow(),
 +        mpDisplay(NULL),
 +        mpGLContext(NULL),
++        mpGLPBufContext(NULL),
++        mpFBConfig(NULL),
 +        mpTextureCache(new TextureCache()),
 +        mnDummyVertexProgram(0),
 +        mnLinearGradientFragmentProgram(0),
@@ -2983,81 +3788,12 @@
 +        unx::XWindowAttributes xAttr;
 +        unx::XGetWindowAttributes( pDisplay, xWindow, &xAttr );
 +        int nScreen = XScreenNumberOfScreen( xAttr.screen );
-+
-+        // select appropriate visual
-+        static int attrList3[] =
-+            {
-+                GLX_RGBA,//only TrueColor or DirectColor
-+                //single buffered
-+                GLX_RED_SIZE,4,//use the maximum red bits, with a minimum of 4 bits
-+                GLX_GREEN_SIZE,4,//use the maximum green bits, with a minimum of 4 bits
-+                GLX_BLUE_SIZE,4,//use the maximum blue bits, with a minimum of 4 bits
-+                GLX_DEPTH_SIZE,0,//no depth buffer
-+                None
-+            };
-+        static int attrList2[] = 
-+            {
-+                GLX_RGBA,//only TrueColor or DirectColor
-+                /// single buffered
-+                GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
-+                GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
-+                GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
-+                GLX_DEPTH_SIZE,1,/// use the maximum depth bits, making sure there is a depth buffer
-+                None
-+            };
-+        static int attrList1[] =
-+            {
-+                GLX_RGBA,//only TrueColor or DirectColor
-+                GLX_DOUBLEBUFFER,/// only double buffer
-+                GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
-+                GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
-+                GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
-+                GLX_DEPTH_SIZE,0,/// no depth buffer
-+                None
-+            };
-+        static int attrList0[] =
-+            {
-+                GLX_RGBA,//only TrueColor or DirectColor
-+                GLX_DOUBLEBUFFER,/// only double buffer
-+                GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
-+                GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
-+                GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
-+                GLX_DEPTH_SIZE,1,/// use the maximum depth bits, making sure there is a depth buffer
-+                None
-+            }; 
-+        static int* attrTable[] = 
-+            {
-+                attrList0,
-+                attrList1,
-+                attrList2,
-+                attrList3,
-+                NULL
-+            };
-+        int** pAttributeTable = attrTable;
 +        
 +        unx::Window childXWindow=0;
-+        unx::XVisualInfo* vi=NULL;
-+        while( *pAttributeTable )
-+        {
-+            // try to find a visual for the current set of attributes
-+            vi = unx::glXChooseVisual( pDisplay,
-+                                       nScreen,
-+                                       *pAttributeTable );
-+            if( vi ) 
-+            {
-+                SystemWindowData winData;
-+                winData.nSize = sizeof(winData);
-+                OSL_TRACE("using VisualID %08X for OpenGL canvas", vi->visualid);
-+                winData.pVisual = (void*)(vi->visual);
-+                mpChildWindow.reset( new SystemChildWindow(&rWindow, 0, &winData, FALSE) );
-+                if( mpChildWindow->GetSystemData() )
-+                    break;
-+                else
-+                    mpChildWindow.reset();
-+            }
-+
-+            ++pAttributeTable;
-+        }
++        unx::XVisualInfo* viWin=NULL;
++        unx::XVisualInfo* viPB=NULL;
++        mpChildWindow=createChildWindow(viWin,viPB,mpFBConfig,
++                                        rWindow,pDisplay,nScreen);
 +
 +        // tweak SysChild window to act as an input-transparent
 +        // overlay
@@ -3071,19 +3807,29 @@
 +            mpChildWindow->SetControlBackground();
 +            mpChildWindow->EnablePaint(FALSE);
 +
-+            unx::GLXContext pContext = 
++            unx::GLXContext pContext1 = 
 +                glXCreateContext(pDisplay,
-+                                 vi,
++                                 viWin,
 +                                 0,
 +                                 GL_TRUE);
-+            mpGLContext = pContext;
++            mpGLContext = pContext1;
++
++            unx::GLXContext pContext2 = 
++                glXCreateContext( pDisplay,
++                                  viPB,
++                                  pContext1,
++                                  GL_TRUE );
++            mpGLPBufContext = pContext2;
++
++            XFree(viWin);
++            XFree(viPB);    
 +
 +            if( !glXMakeCurrent( pDisplay,
 +                                 childXWindow,
-+                                 pContext) )
++                                 pContext1) )
 +            {
-+                glXDestroyContext(pDisplay,
-+                                  pContext);
++                glXDestroyContext(pDisplay, pContext1);
++                glXDestroyContext(pDisplay, pContext2);
 +                throw lang::NoSupportException(
 +                    ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
 +                                         "Could not select OpenGL context!") ),NULL);
@@ -3123,21 +3869,8 @@
 +                }
 +            }
 +
-+            // need the backside for mirror effects
-+            glDisable(GL_CULL_FACE);
-+
-+            // no perspective, we're 2D 
-+            glMatrixMode(GL_PROJECTION);
-+            glLoadIdentity();
-+
-+            // misc preferences
-+            glEnable(GL_POINT_SMOOTH);
-+            glEnable(GL_LINE_SMOOTH);
-+            glEnable(GL_POLYGON_SMOOTH);
-+            glHint(GL_POINT_SMOOTH_HINT,GL_NICEST);
-+            glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
-+            glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);
-+            glShadeModel(GL_FLAT);
++            // init window context
++            initContext();
 +
 +            // compile & link shaders - code courtesy rodo
 +            compileShader(mnDummyVertexProgram, 
@@ -3349,33 +4082,11 @@
 +        if( !bIsVisible || !mpChildWindow || !mpSpriteCanvas )
 +            return false;
 +
-+        const unx::Window aXWindow=mpChildWindow->GetSystemData()->aWindow;
-+        if( !glXMakeCurrent( reinterpret_cast<unx::Display*>(mpDisplay), 
-+                             aXWindow,
-+                             reinterpret_cast<unx::GLXContext>(mpGLContext)) )
-+        {
-+            OSL_TRACE("SpriteDeviceHelper::showBuffer(): cannot activate GL context");
++        if( !activateWindowContext() )
 +            return false;
-+        }
 +
-+        const Size& rOutputSize=mpChildWindow->GetSizePixel();
-+
-+        // use whole window
-+        glViewport( 0,0,
-+                    (GLsizei)rOutputSize.Width(),
-+                    (GLsizei)rOutputSize.Height() );
-+
-+        // model coordinate system is already in device pixel
-+        glMatrixMode(GL_MODELVIEW);
-+        glLoadIdentity();
-+        glTranslated(-1.0, 1.0, 0.0);
-+        glScaled( 2.0  / rOutputSize.Width(), 
-+                  -2.0 / rOutputSize.Height(), 
-+                  1.0 );
-+
-+        // clear to black
-+        glClearColor(0,0,0,0);
-+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
++        const ::Size& rOutputSize=mpChildWindow->GetSizePixel();
++        initTransformation(rOutputSize);
 +
 +        // render the actual spritecanvas content
 +        mpSpriteCanvas->renderRecordedActions();
@@ -3392,7 +4103,29 @@
 +        std::for_each(aSprites.begin(),
 +                      aSprites.end(),
 +                      boost::mem_fn(&CanvasCustomSprite::renderSprite));
++
++
++        // frame counter, other info
++        glMatrixMode(GL_MODELVIEW);
++        glLoadIdentity();
++        glTranslated(-1.0, 1.0, 0.0);
++        glScaled( 2.0  / rOutputSize.Width(), 
++                  -2.0 / rOutputSize.Height(), 
++                  1.0 );
++
++        const double denominator( maLastUpdate.getElapsedTime() );
++        maLastUpdate.reset();
++                        
++        const double fps(denominator == 0.0 ? 100.0 : 1.0/denominator);
++        std::vector<double> aVec; aVec.push_back(fps); 
++        aVec.push_back(maActiveSprites.size());
++        aVec.push_back(mpTextureCache->getCacheSize());
++        aVec.push_back(mpTextureCache->getCacheMissCount());
++        aVec.push_back(mpTextureCache->getCacheHitCount());
++        renderOSD( aVec, 20 );
++
 +        // switch buffer, sync etc.
++        const unx::Window aXWindow=mpChildWindow->GetSystemData()->aWindow;
 +        unx::glXSwapBuffers(reinterpret_cast<unx::Display*>(mpDisplay), 
 +                            aXWindow);
 +        mpChildWindow->Show();        
@@ -3403,7 +4136,7 @@
 +        // indefinitely.
 +        // TODO: have max cache size/LRU time in config, prune only on
 +        // demand
-+        mpTextureCache->flush();
++        mpTextureCache->prune();
 +
 +        return true;
 +    }
@@ -3520,6 +4253,139 @@
 +        setupUniforms(mnLinearGradientProgram, rStartColor, rEndColor, rTexTransform);
 +    }
 +
++    bool SpriteDeviceHelper::activatePBufferContext(const ::basegfx::B2IVector& rSize,
++                                                    unsigned int                PBuffer) const
++    {
++        if( !glXMakeCurrent( reinterpret_cast<unx::Display*>(mpDisplay), 
++                             PBuffer,
++                             reinterpret_cast<unx::GLXContext>(mpGLPBufContext)) )
++        {
++            OSL_TRACE("SpriteDeviceHelper::activatePBufferContext(): cannot activate GL context");
++            return false;
++        }
++
++        initContext();
++        initTransformation(
++            ::Size(
++                rSize.getX(),
++                rSize.getY()));
++
++        return true;
++    }
++
++    bool SpriteDeviceHelper::activateWindowContext() const
++    {
++        const unx::Window aXWindow=mpChildWindow->GetSystemData()->aWindow;
++        if( !glXMakeCurrent( reinterpret_cast<unx::Display*>(mpDisplay), 
++                             aXWindow,
++                             reinterpret_cast<unx::GLXContext>(mpGLContext)) )
++        {
++            OSL_TRACE("SpriteDeviceHelper::activateWindowContext(): cannot activate GL context");
++            return false;
++        }
++
++        return true;
++    }
++
++    bool SpriteDeviceHelper::updatePBufferTexture( const ::basegfx::B2IVector& rSize,
++                                                   unsigned int                nTextId ) const
++    {        
++        glBindTexture( GL_TEXTURE_2D, nTextId );
++        glEnable(GL_TEXTURE_2D);
++        glCopyTexSubImage2D( GL_TEXTURE_2D, 
++                             0, 0, 0, 0, 0, 
++                             rSize.getX(), 
++                             rSize.getY() );
++        glBindTexture(GL_TEXTURE_2D, 0);
++
++        return true;
++    }
++
++    namespace
++    {
++        class BufferContextImpl : public IBufferContext
++        {
++            ::basegfx::B2IVector       maSize;
++            const SpriteDeviceHelper&  mrDeviceHelper;
++            unx::GLXPbuffer            mpPBuffer;
++            unx::Display*              mpDisplay;
++            unsigned int               mnTexture;
++
++            virtual bool startBufferRendering()
++            {
++                return mrDeviceHelper.activatePBufferContext(maSize,mpPBuffer);
++            }
++
++            virtual bool endBufferRendering()
++            {
++                mrDeviceHelper.updatePBufferTexture(maSize,mnTexture);
++                if( !mrDeviceHelper.activateWindowContext() )
++                    return false;
++
++                glBindTexture( GL_TEXTURE_2D, mnTexture );
++
++                return true;
++            }
++            
++        public:
++            BufferContextImpl(const SpriteDeviceHelper&   rDeviceHelper,
++                              unx::GLXPbuffer             pBuffer,
++                              unx::Display*               pDisplay,
++                              const ::basegfx::B2IVector& rSize) :
++                maSize(rSize),
++                mrDeviceHelper(rDeviceHelper),
++                mpPBuffer(pBuffer),
++                mpDisplay(pDisplay),
++                mnTexture(0)
++            {
++                glGenTextures( 1, &mnTexture );
++#if 1
++                glBindTexture( GL_TEXTURE_2D, mnTexture );
++                glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
++                glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
++                glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 
++                              maSize.getX(), maSize.getY(),
++                              0, GL_RGBA, GL_UNSIGNED_BYTE, new int[maSize.getX()*maSize.getY()] );
++#endif
++            }
++
++            ~BufferContextImpl()
++            {
++#if 0
++                glBindTexture(GL_TEXTURE_2D, 0);
++                glDeleteTextures( 1, &mnTexture );
++                glXDestroyPbuffer( mpDisplay, mpPBuffer );
++#endif
++            }
++        };
++    }
++
++    IBufferContextSharedPtr SpriteDeviceHelper::createBufferContext(const ::basegfx::B2IVector& rSize) const
++    {
++        int pBufAttribs[] = 
++            {
++                GLX_PBUFFER_WIDTH,   rSize.getX(),
++                GLX_PBUFFER_HEIGHT,  rSize.getY(),
++                GLX_LARGEST_PBUFFER, False,
++                None
++            };
++        
++        unx::GLXPbuffer pBuffer;
++        pBuffer = unx::glXCreatePbuffer( reinterpret_cast<unx::Display*>(mpDisplay),
++                                         *reinterpret_cast<unx::GLXFBConfig*>(mpFBConfig),
++                                         pBufAttribs );
++
++        IBufferContextSharedPtr pRet;
++        if( pBuffer )
++            pRet.reset(new BufferContextImpl(
++                           *this,
++                           pBuffer,
++                           reinterpret_cast<unx::Display*>(mpDisplay),
++                           rSize));
++
++        return pRet;
++    }
++
 +    TextureCache& SpriteDeviceHelper::getTextureCache() const
 +    {
 +        return *mpTextureCache;
@@ -3527,10 +4393,10 @@
 +}
 diff --git canvas/source/opengl/ogl_spritedevicehelper.hxx canvas/source/opengl/ogl_spritedevicehelper.hxx
 new file mode 100644
-index 0000000..bd4dfa1
+index 0000000..6c02829
 --- /dev/null
 +++ canvas/source/opengl/ogl_spritedevicehelper.hxx
-@@ -0,0 +1,152 @@
+@@ -0,0 +1,176 @@
 +/*************************************************************************
 + *
 + *    OpenOffice.org - a multi-platform office productivity suite
@@ -3550,10 +4416,13 @@
 +#define OGL_SPRITEDEVICEHELPER_HXX
 +
 +#include <rtl/ref.hxx>
++#include <canvas/elapsedtime.hxx>
 +#include <com/sun/star/rendering/XGraphicDevice.hpp>
 +#include <boost/utility.hpp>
 +#include <boost/shared_ptr.hpp>
 +
++#include "ogl_buffercontext.hxx"
++
 +#include <set>
 +
 +
@@ -3629,19 +4498,35 @@
 +        void show( const ::rtl::Reference< CanvasCustomSprite >& );
 +        void hide( const ::rtl::Reference< CanvasCustomSprite >& );
 +
++        /// enable linear gradient shader "texture" with given parameters
 +        void useLinearGradientShader( const ::com::sun::star::rendering::ARGBColor& rStartColor,
 +                                      const ::com::sun::star::rendering::ARGBColor& rEndColor,
 +                                      const ::basegfx::B2DHomMatrix&                rTexTransform );
++        /// enable radial gradient shader "texture" with given parameters
 +        void useRadialGradientShader( const ::com::sun::star::rendering::ARGBColor& rStartColor,
 +                                      const ::com::sun::star::rendering::ARGBColor& rEndColor,
 +                                      const ::basegfx::B2DHomMatrix&                rTexTransform );
++        /// enable rectangular gradient shader "texture" with given parameters
 +        void useRectangularGradientShader( const ::com::sun::star::rendering::ARGBColor& rStartColor,
 +                                           const ::com::sun::star::rendering::ARGBColor& rEndColor,
 +                                           const ::basegfx::B2DHomMatrix&                rTexTransform );
 +
++        /// create a pbuffer context (for rendering into background surface)
++        IBufferContextSharedPtr createBufferContext(const ::basegfx::B2IVector& rSize) const;
++
 +        /// Get instance of internal texture cache
 +        TextureCache& getTextureCache() const;
 +
++        ////////////////////////////////////////////////////////
++
++        // nobody except IBufferContext implementations are supposed
++        // to use this
++        bool activatePBufferContext(const ::basegfx::B2IVector& rSize,
++                                    unsigned int                PBuffer) const;
++        bool activateWindowContext() const;
++        bool updatePBufferTexture( const ::basegfx::B2IVector&,
++                                   unsigned int ) const;
++
 +    private:
 +        void resize( const ::basegfx::B2IVector& rNewSize );
 +
@@ -3665,9 +4550,14 @@
 +
 +        std::set< ::rtl::Reference< CanvasCustomSprite > > maActiveSprites;
 +
++        /// For the frame counter timings
++        ::canvas::tools::ElapsedTime					   maLastUpdate;
++
 +        boost::shared_ptr<SystemChildWindow>               mpChildWindow;
 +        void*                                              mpDisplay;
 +        void*                                              mpGLContext;
++        void*                                              mpGLPBufContext;
++        void*                                              mpFBConfig;
 +
 +        boost::shared_ptr<TextureCache>                    mpTextureCache;
 +
@@ -4002,10 +4892,10 @@
 +#endif
 diff --git canvas/source/opengl/ogl_texturecache.cxx canvas/source/opengl/ogl_texturecache.cxx
 new file mode 100644
-index 0000000..d65cef2
+index 0000000..07ba85a
 --- /dev/null
 +++ canvas/source/opengl/ogl_texturecache.cxx
-@@ -0,0 +1,95 @@
+@@ -0,0 +1,132 @@
 +/*************************************************************************
 + *
 + *    OpenOffice.org - a multi-platform office productivity suite
@@ -4039,7 +4929,10 @@
 +
 +namespace oglcanvas
 +{
-+    TextureCache::TextureCache() : maCache(101) 
++    TextureCache::TextureCache() : 
++        maCache(101),
++        mnMissCount(0),
++        mnHitCount(0)
 +    {}
 +
 +    TextureCache::~TextureCache()
@@ -4057,11 +4950,41 @@
 +        const TextureCacheMapT::const_iterator aEnd=maCache.end();
 +        while( aCurr != aEnd )
 +        {
-+            glDeleteTextures(1, &aCurr->second);
++            glDeleteTextures(1, &aCurr->second.nTexture);
 +            ++aCurr;
 +        }
 +
 +        maCache.clear();
++        mnMissCount = 0;
++        mnHitCount  = 0;
++    }
++
++    void TextureCache::prune()
++    {
++        // un-bind any texture
++        glBindTexture(GL_TEXTURE_2D, 0);
++
++        // delete already "old" textures, mark "new" entries "old"
++        TextureCacheMapT::iterator aNext;
++        TextureCacheMapT::iterator aCurr=maCache.begin();
++        const TextureCacheMapT::iterator aEnd=maCache.end();
++        while( aCurr != aEnd )
++        {
++            aNext=aCurr; ++aNext;
++            if( aCurr->second.bOld )
++            {
++                glDeleteTextures(1, &aCurr->second.nTexture);
++                maCache.erase(aCurr);
++            }
++            else
++            {
++                aCurr->second.bOld = true;
++            }
++            aCurr=aNext;
++        }
++
++        mnMissCount = 0;
++        mnHitCount  = 0;
 +    }
 +
 +    unsigned int TextureCache::getTexture( const geometry::IntegerSize2D& rPixelSize,
@@ -4071,7 +4994,7 @@
 +        unsigned int nTexture(0);
 +
 +        // texture already cached?
-+        TextureCacheMapT::const_iterator aCacheEntry;
++        TextureCacheMapT::iterator aCacheEntry;
 +        if( (aCacheEntry=maCache.find(nPixelCrc32)) == maCache.end() )
 +        {
 +            // nope, insert new entry
@@ -4090,23 +5013,27 @@
 +                         GL_UNSIGNED_INT_8_8_8_8_REV,
 +                         pPixel);
 +
-+            maCache[nPixelCrc32] = nTexture;
++            maCache[nPixelCrc32].nTexture = nTexture;
++            ++mnMissCount;
++
 +            return nTexture;
 +        }
 +        else
 +        {
-+            nTexture = aCacheEntry->second;
++            nTexture = aCacheEntry->second.nTexture;
++            aCacheEntry->second.bOld = false;
++            ++mnHitCount;
 +        }
 +
-+        return nTexture;        
++        return nTexture;
 +    }
 +}
 diff --git canvas/source/opengl/ogl_texturecache.hxx canvas/source/opengl/ogl_texturecache.hxx
 new file mode 100644
-index 0000000..b24436f
+index 0000000..344e608
 --- /dev/null
 +++ canvas/source/opengl/ogl_texturecache.hxx
-@@ -0,0 +1,45 @@
+@@ -0,0 +1,68 @@
 +/*************************************************************************
 + *
 + *    OpenOffice.org - a multi-platform office productivity suite
@@ -4140,14 +5067,37 @@
 +        TextureCache();
 +        ~TextureCache();
 +        
-+        /// clear whole cache
++        /// clear whole cache, reset statistic counters
 +        void flush();
++
++        /** prune old entries from cache
++            
++            Everytime this method is called, all cache entries are set
++            to "old". If subsequently not used by getTexture(),
++            they'll be entitled for expunge on the next prune()
++            call. Resets statistic counters.
++         */
++        void prune();
++
++        /// Statistics
++        size_t getCacheSize() const { return maCache.size(); };
++        sal_uInt32 getCacheMissCount() const { return mnMissCount; }
++        sal_uInt32 getCacheHitCount() const { return mnHitCount; }
++
 +        unsigned int getTexture( const ::com::sun::star::geometry::IntegerSize2D& rPixelSize,
 +                                 const sal_Int8*                                  pPixel, 
 +                                 sal_uInt32                                       nPixelCrc32) const;
 +    private:
-+        typedef std::hash_map<sal_uInt32,unsigned int> TextureCacheMapT;
++        struct CacheEntry
++        { 
++            CacheEntry() : nTexture(0), bOld(false) {} 
++            unsigned int nTexture; 
++            bool bOld; 
++        };
++        typedef std::hash_map<sal_uInt32,CacheEntry> TextureCacheMapT;
 +        mutable TextureCacheMapT maCache;
++        mutable sal_uInt32       mnMissCount;
++        mutable sal_uInt32       mnHitCount;
 +    };
 +}
 +
@@ -4543,6 +5493,24 @@
  #include <vos/mutex.hxx>
  #include <vcl/svapp.hxx>
  #include <cppcanvas/vclfactory.hxx>
+diff --git sd/source/ui/slideshow/slideshowimpl.cxx sd/source/ui/slideshow/slideshowimpl.cxx
+index 0038858..beb4f2d 100644
+--- sd/source/ui/slideshow/slideshowimpl.cxx
++++ sd/source/ui/slideshow/slideshowimpl.cxx
+@@ -1852,7 +1852,12 @@ IMPL_LINK( SlideshowImpl, updateHdl, Timer*, EMPTYARG )
+ 			else
+ */
+ 			{
+-                const float MIN_UPDATE = 0.05f; // do not wait less than 50 ms
++                // Avoid busy loop when the previous call to update()
++                // returns 0.  The minimum value is small enough to allow
++                // high frame rates.  Values larger than 0 are typically
++                // also larger then the small minimum value and thus are
++                // used to determine the frame rate.
++                const float MIN_UPDATE = 0.01f; // 10ms corresponds to 100 frames per second.
+                 if( fUpdate < MIN_UPDATE )
+                     fUpdate = MIN_UPDATE;
+                 else
 diff --git sd/source/ui/slideshow/slideshowviewimpl.cxx sd/source/ui/slideshow/slideshowviewimpl.cxx
 index e20921c..f3532bb 100644
 --- sd/source/ui/slideshow/slideshowviewimpl.cxx



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]