Author: alg
Date: Mon Jun 23 16:45:11 2014
New Revision: 1604874

URL: http://svn.apache.org/r1604874
Log:
i125111 limit mem footprint for GraphicObjects in 32Bit environments

Modified:
    openoffice/branches/AOO410/main/   (props changed)
    openoffice/branches/AOO410/main/svtools/inc/svtools/grfmgr.hxx
    openoffice/branches/AOO410/main/svtools/source/graphic/grfmgr.cxx
    openoffice/branches/AOO410/main/svtools/source/graphic/grfmgr2.cxx
    openoffice/branches/AOO410/main/sw/source/core/doc/notxtfrm.cxx
    openoffice/branches/AOO410/main/sw/source/core/graphic/ndgrf.cxx
    openoffice/branches/AOO410/main/vcl/win/source/gdi/salbmp.cxx

Propchange: openoffice/branches/AOO410/main/
------------------------------------------------------------------------------
  Merged /openoffice/trunk/main:r1603941,1604028

Modified: openoffice/branches/AOO410/main/svtools/inc/svtools/grfmgr.hxx
URL: 
http://svn.apache.org/viewvc/openoffice/branches/AOO410/main/svtools/inc/svtools/grfmgr.hxx?rev=1604874&r1=1604873&r2=1604874&view=diff
==============================================================================
--- openoffice/branches/AOO410/main/svtools/inc/svtools/grfmgr.hxx (original)
+++ openoffice/branches/AOO410/main/svtools/inc/svtools/grfmgr.hxx Mon Jun 23 
16:45:11 2014
@@ -207,7 +207,10 @@ private:
        Timer*                                  mpSwapOutTimer;
        GrfSimpleCacheObj*              mpSimpleCache;
     sal_uLong                   mnAnimationLoopCount;
-       void*                   mpDummy1;
+
+    // a unique increasing ID to be able to say which data change is older
+    sal_uLong               mnDataChangeTimeStamp;
+
        void*                   mpDummy2;
        sal_Bool                                mbAutoSwapped   : 1;
        sal_Bool                                mbTransparent   : 1;
@@ -299,6 +302,10 @@ private:
 
                                                        DECL_LINK( 
ImplAutoSwapOutHdl, void* );
 
+    // Handle evtl. needed AfterDataChanges, needs to be called when new
+    // graphic data is swapped in/added to the GraphicManager
+    void ImplAfterDataChange();
+
 protected:
 
        virtual void                    GraphicManagerDestroyed();
@@ -481,6 +488,12 @@ public:
         double fTopCrop, 
         double fRightCrop, 
         double fBottomCrop) const;
+
+    // read access
+    sal_uLong GetDataChangeTimeStamp() const { return mnDataChangeTimeStamp; }
+
+    // restart SwapOut timer; this is like touching in a cache to reset to the 
full timeout value
+    void restartSwapOutTimer() const;
 };
 
 // ------------------
@@ -545,6 +558,15 @@ private:
 
        ByteString              SVT_DLLPRIVATE ImplGetUniqueID( const 
GraphicObject& rObj ) const;
 
+    // This method allows to check memory footprint for all currently swapped 
in GraphicObjects on this GraphicManager
+    // which are based on Bitmaps. This is needed on 32Bit systems and only 
does something on those systems. The problem
+    // to solve is that normally the SwapOut is timer-driven, but even with 
short timer settings there are situations
+    // where this does not trigger - or in other words: A maximum limitation 
for GraphicManagers was not in place before.
+    // For 32Bit systems this leads to situations where graphics will be 
missing. This method will actively swap out
+    // the longest swapped in graphics until a maximum memory boundary 
(derived from user settings in tools/options/memory)
+    // is no longer exceeded
+    void ImplCheckSizeOfSwappedInGraphics();
+
 public:
 
                                        GraphicManager( sal_uLong nCacheSize = 
10000000UL, sal_uLong nMaxObjCacheSize = 2400000UL );

Modified: openoffice/branches/AOO410/main/svtools/source/graphic/grfmgr.cxx
URL: 
http://svn.apache.org/viewvc/openoffice/branches/AOO410/main/svtools/source/graphic/grfmgr.cxx?rev=1604874&r1=1604873&r2=1604874&view=diff
==============================================================================
--- openoffice/branches/AOO410/main/svtools/source/graphic/grfmgr.cxx (original)
+++ openoffice/branches/AOO410/main/svtools/source/graphic/grfmgr.cxx Mon Jun 
23 16:45:11 2014
@@ -76,6 +76,19 @@ struct GrfSimpleCacheObj
 
 TYPEINIT1_AUTOFACTORY( GraphicObject, SvDataCopyStream );
 
+// unique increasing ID for being able to detect the GraphicObject with the
+// oldest last data changes
+static sal_uLong aIncrementingTimeOfLastDataChange = 1;
+
+void GraphicObject::ImplAfterDataChange()
+{
+    // set unique timestamp ID of last data change
+    mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++;
+
+    // check memory footprint of all GraphicObjects managed and evtl. take 
action
+    GetGraphicManager().ImplCheckSizeOfSwappedInGraphics();
+}
+
 // 
-----------------------------------------------------------------------------
 
 GraphicObject::GraphicObject( const GraphicManager* pMgr ) :
@@ -173,6 +186,9 @@ void GraphicObject::ImplConstruct()
        mbAutoSwapped = sal_False;
        mbIsInSwapIn = sal_False;
        mbIsInSwapOut = sal_False;
+
+    // Init with a unique, increasing ID
+    mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++;
 }
 
 // 
-----------------------------------------------------------------------------
@@ -290,6 +306,9 @@ void GraphicObject::ImplAutoSwapIn()
                        if( !mbAutoSwapped && mpMgr )
                                mpMgr->ImplGraphicObjectWasSwappedIn( *this );
                }
+
+        // Handle evtl. needed AfterDataChanges
+        ImplAfterDataChange();
        }
 }
 
@@ -914,6 +933,9 @@ void GraphicObject::SetGraphic( const Gr
 
        if( mpSwapOutTimer )
                mpSwapOutTimer->Start();
+
+    // Handle evtl. needed AfterDataChanges
+    ImplAfterDataChange();
 }
 
 // 
-----------------------------------------------------------------------------
@@ -1255,7 +1277,9 @@ sal_Bool GraphicObject::SwapIn()
                bRet = sal_True;
        }
        else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic 
) )
+    {
                bRet = sal_True;
+    }
        else
        {
                bRet = maGraphic.SwapIn();
@@ -1265,8 +1289,13 @@ sal_Bool GraphicObject::SwapIn()
        }
 
        if( bRet )
+    {
                ImplAssignGraphicData();
 
+        // Handle evtl. needed AfterDataChanges
+        ImplAfterDataChange();
+    }
+
        return bRet;
 }
 
@@ -1282,7 +1311,9 @@ sal_Bool GraphicObject::SwapIn( SvStream
                bRet = sal_True;
        }
        else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic 
) )
+    {
                bRet = sal_True;
+    }
        else
        {
                bRet = maGraphic.SwapIn( pIStm );
@@ -1292,8 +1323,13 @@ sal_Bool GraphicObject::SwapIn( SvStream
        }
 
        if( bRet )
+    {
                ImplAssignGraphicData();
 
+        //
+        ImplAfterDataChange();
+    }
+
        return bRet;
 }
 
@@ -1453,4 +1489,15 @@ basegfx::B2DVector GraphicObject::calcul
     return basegfx::B2DVector(fFactorX,fFactorY);
 }
 
+// ------------------------------------------------------------------------
+// restart SwapOut timer
+
+void GraphicObject::restartSwapOutTimer() const
+{
+    if( mpSwapOutTimer && mpSwapOutTimer->IsActive() )
+    {
+        mpSwapOutTimer->Start();
+    }
+}
+
 // eof

Modified: openoffice/branches/AOO410/main/svtools/source/graphic/grfmgr2.cxx
URL: 
http://svn.apache.org/viewvc/openoffice/branches/AOO410/main/svtools/source/graphic/grfmgr2.cxx?rev=1604874&r1=1604873&r2=1604874&view=diff
==============================================================================
--- openoffice/branches/AOO410/main/svtools/source/graphic/grfmgr2.cxx 
(original)
+++ openoffice/branches/AOO410/main/svtools/source/graphic/grfmgr2.cxx Mon Jun 
23 16:45:11 2014
@@ -258,7 +258,7 @@ sal_Bool GraphicManager::DrawObj( Output
                                bRet = rCached = sal_True;
                }
        }
-
+ 
        return bRet;
 }
 
@@ -267,7 +267,7 @@ sal_Bool GraphicManager::DrawObj( Output
 void GraphicManager::ImplRegisterObj( const GraphicObject& rObj, Graphic& 
rSubstitute,
                                       const ByteString* pID, const 
GraphicObject* pCopyObj )
 {
-       maObjList.Insert( (void*) &rObj, LIST_APPEND );
+    maObjList.Insert( (void*) &rObj, LIST_APPEND );
        mpCache->AddGraphicObject( rObj, rSubstitute, pID, pCopyObj );
 }
 
@@ -295,16 +295,89 @@ ByteString GraphicManager::ImplGetUnique
 
 // 
-----------------------------------------------------------------------------
 
+namespace
+{
+    struct simpleSortByDataChangeTimeStamp
+    {
+        bool operator() (GraphicObject* p1, GraphicObject* p2) const
+        {
+            return p1->GetDataChangeTimeStamp() < p2->GetDataChangeTimeStamp();
+        }
+    };
+} // end of anonymous namespace
+
+void GraphicManager::ImplCheckSizeOfSwappedInGraphics()
+{
+    // only necessary for 32bit systems
+    if(SAL_TYPES_SIZEOFPOINTER <= 4)
+    {
+        // get the currently used memory footprint of all swapped in bitmap 
graphics
+        // of this graphic manager. Remember candidates in a vector. The size 
in bytes is
+        // already available, thus this loop is not expensive to execute
+        sal_uLong nUsedSize(0);
+        GraphicObject* pObj = 0;
+        std::vector< GraphicObject* > aCandidates;
+
+        for(pObj = (GraphicObject*)maObjList.First(); pObj; pObj = 
(GraphicObject*)maObjList.Next())
+        {
+            if(pObj->meType == GRAPHIC_BITMAP && !pObj->IsSwappedOut() && 
pObj->GetSizeBytes())
+            {
+                aCandidates.push_back(pObj);
+                nUsedSize += pObj->GetSizeBytes();
+            }
+        }
+
+        // detect maximum allowed memory footprint. Use the user-settings of 
MaxCacheSize (defaulted
+        // to 20MB) and add a decent multiplicator (expecrimented to find 
one). Limit to
+        // a useful maximum for 32Bit address space
+
+        // default is 20MB, so allow 200MB initially
+        static sal_uLong aMultiplicator(10); 
+
+        // max at 500MB; I experimented with 800 for debug and 750 for 
non-debug settings (pics start
+        // missing when AOO reaches a mem footprint of 1.5GB) but some secure 
left over space for
+        // app activity is needed
+        static sal_uLong aMaxSize32Bit(500 * 1024 * 1024); 
+
+        // calc max allowed cache size
+        const sal_uLong nMaxCacheSize(::std::min(GetMaxCacheSize() * 
aMultiplicator, aMaxSize32Bit));
+
+        if(nUsedSize >= nMaxCacheSize && !aCandidates.empty())
+        {
+            // if we use more currently, sort by last DataChangeTimeStamp
+            // sort by DataChangeTimeStamp so that the oldest get removed first
+            ::std::sort(aCandidates.begin(), aCandidates.end(), 
simpleSortByDataChangeTimeStamp());
+
+            for(sal_uInt32 a(0); nUsedSize >= nMaxCacheSize && a < 
aCandidates.size(); a++)
+            {
+                // swap out until we have no more or the goal to use less than 
nMaxCacheSize
+                // is reached
+                pObj = aCandidates[a];
+                const sal_uLong nSizeBytes(pObj->GetSizeBytes());
+
+                // do not swap out when we have less than 16KB data objects
+                if(nSizeBytes >= (16 * 1024))
+                {
+                    pObj->FireSwapOutRequest();
+                    nUsedSize = (nSizeBytes < nUsedSize) ? nUsedSize - 
nSizeBytes : 0;
+                }
+            }
+        }
+    }
+}
+
+// 
-----------------------------------------------------------------------------
+
 sal_Bool GraphicManager::ImplFillSwappedGraphicObject( const GraphicObject& 
rObj, Graphic& rSubstitute )
 {
-       return( mpCache->FillSwappedGraphicObject( rObj, rSubstitute ) );
+    return mpCache->FillSwappedGraphicObject(rObj, rSubstitute);
 }
 
 // 
-----------------------------------------------------------------------------
 
 void GraphicManager::ImplGraphicObjectWasSwappedIn( const GraphicObject& rObj )
 {
-       mpCache->GraphicObjectWasSwappedIn( rObj );
+    mpCache->GraphicObjectWasSwappedIn( rObj );
 }
 
 // 
-----------------------------------------------------------------------------

Modified: openoffice/branches/AOO410/main/sw/source/core/doc/notxtfrm.cxx
URL: 
http://svn.apache.org/viewvc/openoffice/branches/AOO410/main/sw/source/core/doc/notxtfrm.cxx?rev=1604874&r1=1604873&r2=1604874&view=diff
==============================================================================
--- openoffice/branches/AOO410/main/sw/source/core/doc/notxtfrm.cxx (original)
+++ openoffice/branches/AOO410/main/sw/source/core/doc/notxtfrm.cxx Mon Jun 23 
16:45:11 2014
@@ -1006,6 +1006,9 @@ void SwNoTxtFrm::PaintPicture( OutputDev
                         aContent,
                         aTargetRange,
                         aTargetRange);
+
+                    // need to reset the timer manually (was in original 
paints at GraphicManager)
+                    rGrfObj.restartSwapOutTimer();
                 }
                        }
                        else

Modified: openoffice/branches/AOO410/main/sw/source/core/graphic/ndgrf.cxx
URL: 
http://svn.apache.org/viewvc/openoffice/branches/AOO410/main/sw/source/core/graphic/ndgrf.cxx?rev=1604874&r1=1604873&r2=1604874&view=diff
==============================================================================
--- openoffice/branches/AOO410/main/sw/source/core/graphic/ndgrf.cxx (original)
+++ openoffice/branches/AOO410/main/sw/source/core/graphic/ndgrf.cxx Mon Jun 23 
16:45:11 2014
@@ -58,14 +58,36 @@
 #include <retrieveinputstreamconsumer.hxx>
 #include <drawinglayer/processor2d/objectinfoextractor2d.hxx>
 #include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
+#include <unotools/cacheoptions.hxx>
 
 using namespace com::sun::star;
 
+#define SWAPGRAPHIC_TIMEOUT     5000
 
-// As Writer graphics are no longer painted via the graphic manager - see 
<SwNoTxtFrm::PaintPicture(..)> -
-// it is needed to swap out the Writer graphics automatically after a certain 
amount of time.
-// --> 5000ms
-#define TIMETOSWAPOUTGRAPHICAUTOMATICALLY 5000
+// For comments see same method used in svx
+sal_uInt32 getCacheTimeInMs()
+{
+    static bool bSetAtAll(true);
+
+    if(bSetAtAll)
+    {
+        static bool bSetToPreferenceTime(true);
+
+        if(bSetToPreferenceTime)
+        {
+            const SvtCacheOptions aCacheOptions;
+            const sal_Int32 
nSeconds(aCacheOptions.GetGraphicManagerObjectReleaseTime());
+
+            return nSeconds * 1000 / 12;
+        }
+        else
+        {
+            return SWAPGRAPHIC_TIMEOUT;
+        }
+    }
+
+    return 0;
+}
 
 // --------------------
 // SwGrfNode
@@ -83,7 +105,7 @@ SwGrfNode::SwGrfNode(
           mbLinkedInputStreamReady( false ),
           mbIsStreamReadOnly( sal_False )
 {
-    maGrfObj.SetSwapStreamHdl( LINK( this, SwGrfNode, SwapGraphic ), 
TIMETOSWAPOUTGRAPHICAUTOMATICALLY );
+    maGrfObj.SetSwapStreamHdl( LINK( this, SwGrfNode, SwapGraphic ), 
getCacheTimeInMs() );
     bInSwapIn = bChgTwipSize = bChgTwipSizeFromPixel = bLoadLowResGrf = 
bFrameInPaint = bScaleImageMap = sal_False;
 
     bGrafikArrived = sal_True;
@@ -102,7 +124,7 @@ SwGrfNode::SwGrfNode(
           mbIsStreamReadOnly( sal_False )
 {
     maGrfObj = rGrfObj;
-    maGrfObj.SetSwapStreamHdl( LINK( this, SwGrfNode, SwapGraphic ), 
TIMETOSWAPOUTGRAPHICAUTOMATICALLY );
+    maGrfObj.SetSwapStreamHdl( LINK( this, SwGrfNode, SwapGraphic ), 
getCacheTimeInMs() );
     if ( rGrfObj.HasUserData() && rGrfObj.IsSwappedOut() )
         maGrfObj.SetSwapState();
     bInSwapIn = bChgTwipSize = bChgTwipSizeFromPixel = bLoadLowResGrf = 
bFrameInPaint = bScaleImageMap = sal_False;
@@ -125,7 +147,7 @@ SwGrfNode::SwGrfNode(
           mbLinkedInputStreamReady( false ),
           mbIsStreamReadOnly( sal_False )
 {
-    maGrfObj.SetSwapStreamHdl( LINK( this, SwGrfNode, SwapGraphic ), 
TIMETOSWAPOUTGRAPHICAUTOMATICALLY );
+    maGrfObj.SetSwapStreamHdl( LINK( this, SwGrfNode, SwapGraphic ), 
getCacheTimeInMs() );
 
     Graphic aGrf;
     aGrf.SetDefaultType();

Modified: openoffice/branches/AOO410/main/vcl/win/source/gdi/salbmp.cxx
URL: 
http://svn.apache.org/viewvc/openoffice/branches/AOO410/main/vcl/win/source/gdi/salbmp.cxx?rev=1604874&r1=1604873&r2=1604874&view=diff
==============================================================================
--- openoffice/branches/AOO410/main/vcl/win/source/gdi/salbmp.cxx (original)
+++ openoffice/branches/AOO410/main/vcl/win/source/gdi/salbmp.cxx Mon Jun 23 
16:45:11 2014
@@ -448,35 +448,43 @@ Gdiplus::Bitmap* WinSalBitmap::ImplCreat
 
         if(pRetval)
         {
-            sal_uInt8* pSrcRGB(pRGB->mpBits);
-            sal_uInt8* pSrcA(pA->mpBits);
-            const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3));
-            const sal_uInt32 nExtraA(pA->mnScanlineSize - nW);
-            const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN);
-            const Gdiplus::Rect aAllRect(0, 0, nW, nH);
-            Gdiplus::BitmapData aGdiPlusBitmapData;
-            pRetval->LockBits(&aAllRect, Gdiplus::ImageLockModeWrite, 
PixelFormat32bppARGB, &aGdiPlusBitmapData);
-
-            // copy data to Gdiplus::Bitmap; format is BGRA; need to mix BGR 
from Bitmap and
-            // A from alpha, so inner loop is needed (who invented BitmapEx..?)
-            for(sal_uInt32 y(0); y < nH; y++)
+            if ( pRetval->GetLastStatus() == Gdiplus::Ok ) // 2nd place to 
secure with new Gdiplus::Bitmap
             {
-                const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1);
-                sal_uInt8* targetPixels = (sal_uInt8*)aGdiPlusBitmapData.Scan0 
+ (nYInsert * aGdiPlusBitmapData.Stride);
-
-                for(sal_uInt32 x(0); x < nW; x++)
+                sal_uInt8* pSrcRGB(pRGB->mpBits);
+                sal_uInt8* pSrcA(pA->mpBits);
+                const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3));
+                const sal_uInt32 nExtraA(pA->mnScanlineSize - nW);
+                const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN);
+                const Gdiplus::Rect aAllRect(0, 0, nW, nH);
+                Gdiplus::BitmapData aGdiPlusBitmapData;
+                pRetval->LockBits(&aAllRect, Gdiplus::ImageLockModeWrite, 
PixelFormat32bppARGB, &aGdiPlusBitmapData);
+
+                // copy data to Gdiplus::Bitmap; format is BGRA; need to mix 
BGR from Bitmap and
+                // A from alpha, so inner loop is needed (who invented 
BitmapEx..?)
+                for(sal_uInt32 y(0); y < nH; y++)
                 {
-                    *targetPixels++ = *pSrcRGB++;
-                    *targetPixels++ = *pSrcRGB++;
-                    *targetPixels++ = *pSrcRGB++;
-                    *targetPixels++ = 0xff - *pSrcA++;
+                    const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1);
+                    sal_uInt8* targetPixels = 
(sal_uInt8*)aGdiPlusBitmapData.Scan0 + (nYInsert * aGdiPlusBitmapData.Stride);
+
+                    for(sal_uInt32 x(0); x < nW; x++)
+                    {
+                        *targetPixels++ = *pSrcRGB++;
+                        *targetPixels++ = *pSrcRGB++;
+                        *targetPixels++ = *pSrcRGB++;
+                        *targetPixels++ = 0xff - *pSrcA++;
+                    }
+
+                    pSrcRGB += nExtraRGB;
+                    pSrcA += nExtraA;
                 }
 
-                pSrcRGB += nExtraRGB;
-                pSrcA += nExtraA;
+                pRetval->UnlockBits(&aGdiPlusBitmapData);
+            }
+            else
+            {
+                delete pRetval;
+                pRetval = NULL;
             }
-
-            pRetval->UnlockBits(&aGdiPlusBitmapData);
         }
     }
 


Reply via email to